Skip to content

AssertionError in FfiHandle.__del__ (assert dropped) at job shutdown with livekit 1.1.20 #845

Description

@khantseithu

Summary

After upgrading to livekit-agents 1.8.4 (which pins livekit==1.1.20), every job shutdown at the end of a voice session prints several AssertionErrors from FfiHandle.__del__:

Exception ignored in: <function FfiHandle.__del__ at 0x...>
Traceback (most recent call last):
  File ".../site-packages/livekit/rtc/_ffi_client.py", line 77, in __del__
    self.dispose()
  File ".../site-packages/livekit/rtc/_ffi_client.py", line 99, in dispose
    assert dropped
           ^^^^^^^
AssertionError:

They appear right after the job's shutdown callbacks run (after UsageCollector summary logging and http_session(): closing the httpclient ctx), six times in our case. The process otherwise shuts down normally — it looks like log noise, but it means a Python FfiHandle is being garbage-collected for a handle the native side has already released.

We did not see this on livekit 1.1.8 (with livekit-agents 1.5.17), although the same assert existed in FfiHandle.dispose() there.

Environment

  • livekit 1.1.20, livekit-agents 1.8.4, livekit-plugins-google 1.8.4
  • Python 3.12, macOS (arm64)
  • Worker started with lk agent dev; session: AgentSession(llm=google.realtime.RealtimeModel(model="gemini-3.8-live")), browser client (livekit-client 2.22.3) receiving transcriptions; the user ends the call from the browser (room.disconnect()).

What we looked at

  • FfiHandle.dispose() sets _disposed = True before dropping, so an explicit dispose() followed by GC can't double-drop — the failing drops come from __del__ on handles that were never disposed from Python but are already gone natively.
  • 1.1.20 newly wraps data stream writer handles in FfiHandle (_register_open / _unregister_open in data_stream.py, _open_stream_writers in participant.py, _dispose_open_stream_writers in room.py). Since agents publish transcriptions over text streams, we suspect writers (or other handles) that the native side frees together with the room, and that Python only collects after that — but we haven't confirmed which handle type is involved.

Expected

No assertion output at shutdown; or, if a native-side release before Python GC is legitimate, __del__ should not assert on it.

Happy to test a fix or add logging (e.g. the handle type in FfiHandle.__repr__) if that helps narrow it down.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions