For the complete documentation index, see llms.txt. This page is also available as Markdown.

Error Handling

The SDK surfaces errors through four channels. Each has a different scope and payload — knowing which one to use for a given scenario is the key to reliable apps.

Channel
Event
When it fires

Transport errors

error

Low-level WebRTC / WebSocket exceptions

Session end

disconnect

Every session end, with a reason code

Server acknowledgments

serverResponse

After every message you send

Silent LLM

llmNoResponse

LLM deliberately chose not to respond

Idle timeout

idleWarning

Server about to disconnect an idle session


error event

Fires for low-level transport exceptions. The payload is unknown because it wraps whatever the underlying transport threw.

client.on('error', (err) => {
  if (err instanceof Error) {
    console.error(err.name, err.message);
  } else {
    console.error(err);
  }
});

Common causes on the WebRTC transport:

Code
Meaning

1

ConnectionError — permission denied, server unreachable, or cancelled

13

NegotiationError — WebRTC negotiation failed

21

DeviceUnsupportedError — microphone or camera not available


disconnect event

Fires on every session end — intentional or not. The payload is a numeric DisconnectReason code.

React

Vanilla JS

Reason code reference

Code
Enum key
Meaning
Auto-retry?

0

UNKNOWN_REASON

Network unavailable or browser went offline — this is the most common reason for an unexpected drop

Yes

1

CLIENT_INITIATED

User called disconnect()

No — intentional

2

DUPLICATE_IDENTITY

Another session with same identity joined

No — prompt user

3

SERVER_SHUTDOWN

Server restarting

Yes — with delay

4

PARTICIPANT_REMOVED

Removed via server API

No

5

ROOM_DELETED

Session closed server-side

No

6

STATE_MISMATCH

Client/server state diverged

Yes

7

JOIN_FAILURE

Failed to join — check config

No — fix config

9

SIGNAL_CLOSE

WebSocket signal channel closed cleanly

Yes

UNKNOWN_REASON vs SIGNAL_CLOSE: Both indicate a network drop and both should trigger a retry. The difference is timing — when the browser goes fully offline (n +avigator.onLine = false), LiveKit fires UNKNOWN_REASON (0) immediately via its off +line detector before the WebSocket even closes. SIGNAL_CLOSE (9) fires when the sig +nal WebSocket itself closes, which requires the network to be partially reachable. In + practice, pulling WiFi or DevTools → Offline always produces UNKNOWN_REASON.

The last reason is also available synchronously on client.state.disconnectReasonnull when connected.


serverResponse event

The server sends an acknowledgment for every message your client sendssendUserTextMessage, updateContext, sendTriggerMessage, toggleTts, etc. Check status to know if the server accepted the request.

React

Vanilla JS

Payload shape

For context-update, extras contains token budget info:


llmNoResponse event

Fires when the LLM deliberately chose not to respond — not an error, but your UI should stop showing a thinking indicator.


idleWarning event

Fires before the server disconnects an idle session. Call resetIdleTimer() on any user activity to keep the session alive.


Reliability patterns

Retry with exponential backoff

The SDK does not auto-reconnect. Implement your own backoff on non-intentional disconnects.

Safe send guard

Check connection state before sending to avoid silent drops.

Protect media control calls

Audio and video control methods are async and can throw on permission denial.

Always unsubscribe

Every client.on(...) call returns an unsubscribe function. Call it on unmount or session teardown.


Quick reference — which channel to use

Scenario
Channel

Network dropped mid-session

disconnectSIGNAL_CLOSE (9)

User pressed disconnect

disconnectCLIENT_INITIATED (1)

Same user opened another tab

disconnectDUPLICATE_IDENTITY (2)

Server maintenance

disconnectSERVER_SHUTDOWN (3)

updateContext rejected by server

serverResponsestatus: 'error'

Dynamic context token budget low

serverResponseextras.remaining_tokens

WebRTC negotiation failed

error — code 13

Microphone permission denied

error — code 1 (sub-reason 0)

LLM decided not to reply

llmNoResponse

Session about to time out

idleWarning

Last updated

Was this helpful?