tall-ability-51442
03/12/2026, 10:11 AMtall-airline-16756
03/12/2026, 10:11 AMtall-airline-16756
03/12/2026, 10:11 AMshutdown_callback being invoked with reason=None.
I checked the LiveKit agent job docs that show how to register shutdown callbacks with ctx.add_shutdown_callback() and explain the framework’s shutdown waiting behavior, but those docs do not define what a None value for the reason parameter means. In other words, reason=None is not explicitly described in the referenced documentation.
To help narrow this down and give a useful answer, could you share a bit more about the situation when you see reason=None?
• Is the shutdown initiated by you (e.g., sending SIGINT/SIGTERM, calling an API) or does it appear spontaneous?
• Are you running with any custom shutdown_process_timeout or other shutdown-related configuration?
• Does this happen every time or only sometimes? If intermittent, are there any related log lines around the callback invocation you can share (timestamps and surrounding messages help)?
• What LiveKit agent version are you running?
With that info I can suggest likely causes and targeted next steps (for example: additional logging to capture the signal source, verifying the agent’s runtime environment for external process restarts, or adjusting shutdown timeouts).
Sources: Job lifecycle | LiveKit Documentationtall-ability-51442
03/12/2026, 10:17 AMtall-airline-16756
03/12/2026, 10:17 AMparticipant.disconnect_reason can be None in the participant_disconnected callback.
The documentation and references list specific disconnect reasons (e.g., CLIENT_INITIATED, ROOM_DELETED, DUPLICATE_IDENTITY, STATE_MISMATCH), but they do not guarantee that a reason is always populated for every disconnect event. In other words, participant.disconnect_reason can be None — the docs do not define it as a guaranteed non-null field.
Common practical causes for disconnect_reason being None include:
• Abrupt network failures or client crashes where the server cannot determine or propagate a specific close reason.
• Timing: the participant may be removed before the reason is set or before the SDK/agent has populated the field that is delivered to your callback.
• SDK/version differences: some SDK builds or versions may not include the reason in every event payload.
• Internal or transient server conditions where a mapped DisconnectReason isn’t available.
Next steps you can take to diagnose and reduce occurrences:
1. Capture surrounding logs for the participant at the time of disconnection (both client and server/agent logs). Timestamps and any close/connection error messages help identify whether the disconnect was abrupt.
2. Note how often this happens and any patterns (specific clients, networks, or rooms).
3. Tell me the LiveKit SDK/agent version you’re using so I can point out any version-specific behavior.
4. If possible, reproduce with verbose logging enabled on client and server to see whether a reason is sent but not surfaced to your callback.
If you share logs or the SDK/agent version and a brief sequence of events when it happens, I can help interpret the logs and suggest targeted changes (e.g., adding retries, increasing logging around close events, or confirming SDK behavior for your version).
Sources: Agent session | LiveKit Documentation | Understanding the STATE_MISMATCH Disconnect Reason | LiveKit | Server-side | livekit/livekit_composite | DeepWikitall-ability-51442
03/12/2026, 10:21 AMtall-airline-16756
03/12/2026, 10:21 AMparticipant.disconnect_reason can be None and why those disconnects might not show up in LiveKit Cloud’s Session Events table, and how your backend can reliably decide which events to act on.
Short answer
• participant.disconnect_reason can be None because the reason isn’t always available or propagated when the disconnection happens (for example, abrupt network failures, client crashes, or timing issues). The docs and event model do list explicit reasons (e.g., CLIENT_INITIATED, ROOM_DELETED, DUPLICATE_IDENTITY, etc.), but they don’t guarantee a reason will be present in every SDK event payload.
• The Cloud Sessions Events table may apply UI-level filtering or processing and therefore may not display every disconnect event. The exact dashboard filters are not documented, so the dashboard should not be relied on as the single source of truth for programmatic logic.
• Use webhooks as the reliable source for lifecycle events — they include a reason field and are intended for backend processing.
Why disconnect reason can be None (practical causes)
• Abrupt network failure or client crash: the server/agent can’t determine or map a tidy DisconnectReason before the participant is removed.
• Timing: the participant may be removed before the reason is set or before the SDK surfaces the reason to your callback.
• SDK/version differences: some SDK versions or language bindings may not populate the reason field in every emitted event.
• Transient/internal conditions: there can be internal cases where a mapped reason isn’t available.
Why you might not see these events in the Cloud Session Events table
• The Cloud dashboard can apply internal filters, sampling, or post-processing to the event stream; those UI-level rules can exclude certain events or noisy/partial events. The specific filtering criteria are not published.
• The dashboard is primarily for human observability; it may not include every low-level or transient event that webhooks or server logs receive.
Recommended approach for your backend (reliable and actionable)
1. Use webhooks as the authoritative event stream
◦ Enable webhooks for your project and receive participant_left, room_finished, and related events on your backend.
◦ Webhook payloads include reason information corresponding to DisconnectReason.
◦ Verify webhook signatures for authenticity and handle retries/idempotency.
1. Treat dashboard visibility as informational only
◦ Don’t depend on the Session Events table for programmatic decisions; use webhooks and server logs instead.
1. Implement defensive handling for None reasons
◦ If reason is None, treat it as an abrupt/unexpected disconnect and apply conservative logic (e.g., mark participant as disconnected, trigger cleanup, and optionally schedule a short grace period to allow reconnect).
◦ Optionally enrich events with context: client-side logs, connection error codes, and timestamps.
1. Use event type + reason to decide importance
◦ Primary event types to act on: participant_left (normal leave), participant_joined, room_finished. Use reason to differentiate cause when present.
◦ Consider these as “important” to handle: explicit CLIENT_INITIATED, ROOM_DELETED, DUPLICATE_IDENTITY, STATE_MISMATCH. If reason is missing, treat as potentially important (unexpected).
1. Logging & instrumentation
◦ Log both webhook payloads and SDK callbacks with timestamps and participant IDs.
◦ If you see frequent None reasons, capture client-side connection errors and agent logs to diagnose patterns.
What I can help with next
• If you share the SDK/agent version and an example webhook or callback payload (with timestamps and surrounding logs), I can help interpret whether that disconnect looks like an abrupt network failure versus a known close reason.
• I can provide a webhook-processing template that handles idempotency, signature verification, and None reasons gracefully.
If you want, paste a sample callback payload or a short log extract of a disconnect where reason was None and I’ll walk through a diagnosis and a suggested backend workflow.
Sources: Why is my Agent insights data missing? | LiveKit | Best practices for managing webhook event streams | LiveKit | server-sdk-js | livekit/livekit_composite | DeepWiki