My livekit agent's shutdown_callback sometimes get...
# ask-ai
t
My livekit agent's shutdown_callback sometimes gets called with reason=None. What does that indicate?
t
Thanks for reaching out, Tom. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about the agent’s
shutdown_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 Documentation
t
Apologies I meant participant_disconnected callback, why there would the participant.disconnect_reason be None?
t
Thanks — I’m responding to your corrected question about why
participant.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 | DeepWiki
t
How come these events don't even display in the livekit cloud's Session's Events table? Is there some filter it's applying? I want to know how my backend can decide which of these are actual important events to handle
t
Thanks — I’m responding to your question about two things: why
participant.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