fix(inference): guard agent sid header against unconnected room#5947
Merged
Conversation
get_inference_headers() accessed ctx.agent.sid, which resolves to rtc.Room.local_participant and raises a bare Exception before the room is connected. STT/TTS websockets that open before ctx.connect() crashed with "cannot access local participant before connecting", since the handler only caught RuntimeError. Guard the access with room.isconnected() (the codebase-standard readiness check used in utils/participant.py and job.py); local_participant is set once on connect and never cleared, so the access cannot raise once isconnected() is True. Room and job ids come from job info and remain available pre-connect, so attribution falls back to room/job level. Adds regression tests covering the unconnected, connected, non-str sid, empty sid, and no-job-context paths. Regression introduced by #5937, latent through #5943. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tinalenguyen
approved these changes
Jun 3, 2026
Bobronium
added a commit
that referenced
this pull request
Jun 3, 2026
New module from main (#5947); it covers get_inference_headers with fakes (no network or credentials), so it's a hermetic unit test. https://claude.ai/code/session_01XvWkVuQVX9kJf3gn9cRXC5 Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a crash in
get_inference_headers()introduced by #5937 and carried through #5943. STT/TTS/LLM inference connections crash withException: cannot access local participant before connectingwhen their websocket opens beforectx.connect()finishes.Root cause
#5937 added
ctx.agent.sidto the header builder.ctx.agentresolves toroom.local_participant, which raises a bareException(notRuntimeError) while the room is unconnected. The surrounding handler only caughtRuntimeError(the no-job-context case), so the exception escaped and killed the STT pump:Before #5937 the function only read
ctx.job.room.sidandctx.job.id(both from job info, available pre-connect), so it never touchedlocal_participant.Fix
Guard the access with
room.isconnected()— the codebase-standard readiness check (utils/participant.py,job.py):rtc.Room._local_participantis assigned once on connect and never cleared (not on disconnect or reconnect), solocal_participantraises only before the first connect — exactly whenisconnected()isFalse. The guard is therefore reliable, not a leaky proxy.MockRoomalready stubsisconnected() -> True, so console/IPC mode is unaffected.The agent id is best-effort attribution (per #5937); room and job ids stay available pre-connect, so attribution falls back to room/job level rather than crashing.
Testing
New
tests/test_inference_utils.py(5 explicit cases): unconnected-room (the regression), connected, non-str sid (#5943 guard), empty sid, and no-job-context. The regression test fails on the pre-fix code with the exact reported error and passes with the fix.ruff format --check+ruff check: cleanmypy -p livekit.agents: no new errors ininference/Note
For a websocket opened before
ctx.connect(), the agent id stays omitted for that connection's lifetime (headers are fixed at open time). That's by design for a best-effort attribution header, not a defect.🤖 Generated with Claude Code