Error Handling
The SDK exposes error-related behavior through three main channels:
Use
telnyx.ready to know when the client is authenticated and the gateway is ready. Do not treat readiness as a notification case.
What your application should react to
For production integrations, handle these events explicitly:
Do not treat every warning as a failed call. Media/signaling recovery warnings are intentionally emitted before the SDK attempts recovery, so your application can show a short degraded/reconnecting state while the SDK handles the recovery path.
Version note: The structured error and warning system (TELNYX_ERROR_CODES,telnyx.warning,TelnyxError) was introduced after v2.25.25. Exponential-backoff reconnection and browseronline/offlinehints (see Reconnection Behavior) ship in the next release. If you are on v2.25.25, see Error handling in v2.25.25 below.
Structured Errors (telnyx.error)
telnyx.error is the primary error surface. Listen for it to handle authentication failures, media errors, and connection issues.
Imports
Error event payload structure
Everytelnyx.error event is one of two shapes. Always check isMediaRecoveryErrorEvent(event) first, because the media-recovery variant carries callable recovery helpers.
Standard error event (the common case):
mediaPermissionsRecovery.enabled is set and getUserMedia() fails while answering):
error object (TelnyxError / ITelnyxError) exposes:
fatalvsrecoverable— two distinct fields, two distinct purposes:Recommended listener order: (1) check
event.error.fatal(always present on every error): tells your app whether the SDK has a recovery path.true= the SDK will not recover — take action now.false= the SDK is handling it — wait or continue.event.recoverable(only on media-permission recovery events): signals the app can recover via theresume()/reject()helpers. Onlyevent.recoverable === trueis meaningful;recoverableis absent on standard errors — do not branch onevent.recoverable === false.isMediaRecoveryErrorEvent(event)first, (2) then checkevent.error.fatalto decide whether to take action or wait, (3) then branch onevent.error.codefor tailored UX.
Getting and filtering errors by code
Media permission recovery
WhenmediaPermissionsRecovery.enabled is configured and getUserMedia() fails while answering a call, the error event includes recoverable: true with resume() and reject() callbacks:
Fatal errors and recommended handling
Fatal errors are situations the SDK will not recover from. When a fatal error fires, the affected call or session is dead — the SDK will not retry, reconnect, or reattach on its own. Your application must take the action described below. Every error event includesevent.error.fatal — a boolean that tells your app whether the SDK has a recovery path. true means the situation is terminal and you must act; false means the SDK is handling it (wait or continue). The Fatal? column below mirrors this field.
Uncommon errors — when to investigate.Errors that are not fatal by default (the SDK handles or continues):SDP_CREATE_OFFER_FAILED(40001),SDP_CREATE_ANSWER_FAILED(40002),SDP_SET_LOCAL_DESCRIPTION_FAILED(40003),SDP_SET_REMOTE_DESCRIPTION_FAILED(40004),PEER_CLOSED_DURING_INIT(44005), andWEBSOCKET_CONNECTION_FAILED(45001) are not expected during normal operation. If any of these recurs a few times or more, share the call with Telnyx support for investigation — their occurrence is most likely not caused by user actions and may indicate a browser, network, or server-side issue.
HOLD_FAILED (44001), BYE_SEND_FAILED (44003), SUBSCRIBE_FAILED (44004), WEBSOCKET_ERROR (45002), GATEWAY_FAILED (45004), ICE_RESTART_FAILED (47001), NETWORK_OFFLINE (48001). Two exceptions to know:
AUTHENTICATION_REQUIRED(46003) is non-fatal by default but becomes fatal whenautoReconnect: false. Re-authenticate usingclient.login().- The three media errors (
42001–42003) become recoverable (non-fatal) whenmediaPermissionsRecovery.enabledis set.
Re-authenticate without recreating the instance. ForLOGIN_FAILED(46001),INVALID_CREDENTIALS(46002), andAUTHENTICATION_REQUIRED(46003), useclient.login()on the existing connection:
Errors and warnings you should handle explicitly
These are the high-impact errors and warnings we recommend handling explicitly in every production integration. They are also marked ⚠️ in the reference tables below. Important errors (handle ontelnyx.error):
Important warnings (handle on
telnyx.warning):
Error code reference
Each error below is classified as fatal or non-fatal and includes what the SDK does automatically versus what you should do.SDP errors
Media errors
Call-control errors
ICE restart errors
WebSocket and transport errors
autoReconnectis enabled by default. Unless you explicitly setautoReconnect: false, the SDK handles reconnection automatically forWEBSOCKET_ERROR,GATEWAY_FAILED, and signaling-health recovery. You only need to callclient.connect()manually if you disabledautoReconnector afterRECONNECTION_EXHAUSTED.
Authentication and session errors
Re-authenticate without recreating the instance. ForLOGIN_FAILED(46001),INVALID_CREDENTIALS(46002), andAUTHENTICATION_REQUIRED(46003), useclient.login()to re-authenticate on the existing connection:
Structured Warnings (telnyx.warning)
Warnings are never fatal. They describe degraded behavior, quality issues, or situations that may need user action before the session breaks. The SDK continues operating after emitting a warning.
Imports
Warning event payload structure
Every warning event includes a structuredwarning object and the SDK sessionId. When a warning is associated with a specific call, callId is included. Recovery-related warnings add reason (and source for signaling recovery) for diagnostics:
warning object (ITelnyxWarning) exposes:
Use
warning.code for application logic. Use warning.message, warning.causes, and warning.solutions for support tooling or user-facing troubleshooting copy.
Getting and filtering warnings by code
Warning code reference
Network quality warnings
Data-flow warnings
Call connection warnings
Authentication and session warnings
Signaling health and recovery warnings
Signaling health warnings are emitted when the SDK detects a half-dead WebSocket during an active call — the browser still reports the socket as
OPEN, but no signaling bytes are flowing after a network interface change, VPN change, NAT timeout, or proxy/load-balancer drop. The SDK decides one recovery path:
- If signaling is unhealthy, it reconnects the WebSocket and reattaches active calls (
SIGNALING_RECOVERY_REQUIRED). - If signaling is healthy but media is unhealthy, it attempts ICE restart (
MEDIA_RECOVERY_REQUIRED). - It does not run both recovery paths at the same time.
online/offline events are treated as low-confidence hints and may accelerate a signaling health probe, but they do not directly trigger recovery.
Your application should keep the current call visible, show a reconnecting/degraded state, and wait for the next callUpdate, telnyx.ready, warning, or final hangup before cleaning up the UI.
Call Termination Data
When a call reacheshangup, inspect these fields on the Call object:
Common causes:
Socket Events
telnyx.socket.close
Delivers the browser CloseEvent. During a forced safety cleanup, the SDK emits a synthetic abnormal close with code: 1006 and wasClean: false.
Useful close codes:
telnyx.socket.error
Delivers { error: ErrorEvent, sessionId: string }. Browsers expose very little information for WebSocket errors. The SDK also emits telnyx.error with code 45002 (WEBSOCKET_ERROR) when ws.onerror fires.
Connection State Helpers
The browser session exposes WebSocket state helpers onclient.connection:
Example:
Reconnection Behavior
Ontelnyx.socket.close or telnyx.socket.error, the SDK clears subscriptions and resets gateway readiness state. autoReconnect is enabled by default; unless you set autoReconnect: false, the SDK automatically schedules connect(). Automatic reconnect stops after maxReconnectAttempts attempts (default: 10), or runs indefinitely when maxReconnectAttempts: 0.
Reconnect backoff
Reconnect attempts use exponential backoff with jitter (not a fixed/random delay):- Base delay starts at ~1s and doubles per attempt (~1s → ~2s → ~4s → ~8s → ~16s), capped at 30s.
- ±25% jitter is applied to avoid thundering-herd reconnects.
- The backoff counter resets only on a confirmed healthy registration (
REGED), not merely on socket open.
Browser online/offline handling
Browseronline/offline events are treated as low-confidence hints, not direct recovery triggers:
offlineemits theNETWORK_OFFLINE(48001) error for backward compatibility/telemetry and may accelerate a signaling health probe. It does not force a reconnect.onlineclears the browser-reported offline state for diagnostics but does not trigger recovery.- Recovery starts only from SDK-owned health evidence: liveness probe timeout, critical request timeout, peer failure, or no-RTP.
Socket close/error dedupe
When a socket fails, browsers commonly emit bothSocketError and SocketClose for the same disconnect. The SDK dedupes these by socket generation so a duplicate event cannot clear an already-scheduled reconnect timer or schedule a redundant reconnect. Stale events from an older, already-replaced socket are ignored.
Gateway retry behavior
- UNREGED / NOREG: Up to 5 registration retries with exponential backoff. After that,
LOGIN_FAILED(46001). - FAILED / FAIL_WAIT / TIMEOUT:
GATEWAY_FAILED(45004) emitted on first detection. The SDK retries with exponential backoff untilRECONNECTION_EXHAUSTED(45003).
Keeping media alive
IfkeepConnectionAliveOnSocketClose is true, the SDK preserves active peer connections while signaling reconnects. Recovery can create a new Call object with recoveredCallId.
Clearing reconnect stickiness
By default, the SDK reconnects to the sameb2bua-rtc instance. To break this stickiness and route to a different instance:
Note:clearReconnectToken()andskipLastVoiceSdkIdare available in@telnyx/webrtc@2.26.4.
Error Handling in v2.25.25
Important: If you are using SDK version 2.25.25, the error handling architecture is fundamentally different from the current version. This section documents the v2.25.25 error surface.
What is different in v2.25.25
Error events in v2.25.25
In v2.25.25, errors are emitted throughtelnyx.error and telnyx.notification:
telnyx.error — Session-level errors with raw Error objects (no .code property):
telnyx.notification — Carries both call lifecycle updates and error information. This is the only recommended way to handle media, peer connection, and signaling errors in v2.25.25. Do not listen for telnyx.rtc.mediaError, telnyx.rtc.peerConnectionFailureError, or telnyx.rtc.peerConnectionSignalingStateClosed directly — those are internal events. Use telnyx.notification instead:
Authentication errors in v2.25.25
Login errors are emitted ontelnyx.error with a type field for invalid credentials. You can re-authenticate using client.login() without recreating the TelnyxRTC instance:
Reconnection in v2.25.25
Reconnection behavior differs from the current version:autoReconnectis enabled by default; the SDK automatically reconnects unless you setautoReconnect: false- Reconnect uses a fixed/random 2-6 second delay (current SDK uses exponential backoff with jitter, capped at 30s)
- Browser
online/offlineevents directly drive reconnect (current SDK treats them as low-confidence hints) - No
maxReconnectAttemptsoption (current SDK defaults to 10 attempts and supportsmaxReconnectAttempts: 0for unlimited attempts) - No
clearReconnectToken()method - No
skipLastVoiceSdkIdoption keepConnectionAliveOnSocketCloseis available
Migrating from v2.25.25 to the latest
If you are upgrading from v2.25.25 to the latest version:- Replace
telnyx.notificationerror handling — usetelnyx.errorfor fatal errors andtelnyx.warningfor non-fatal conditions. Keeptelnyx.notificationfor call lifecycle only. - Replace
notification.type === 'userMediaError'handling withtelnyx.errorlistener switching onevent.error.code(42001,42002,42003). - Replace
notification.type === 'peerConnectionFailureError'handling withtelnyx.warninglistener forPEER_CONNECTION_FAILED(33004). - Replace
notification.type === 'signalingStateClosed'handling withtelnyx.warninglistener for the appropriate warning code. - Replace
ERROR_TYPE.invalidCredentialsOptionschecks withevent.error.code === TELNYX_ERROR_CODES.INVALID_CREDENTIALS(46002). Useclient.login()to re-authenticate without recreating theTelnyxRTCinstance. - Import new symbols:
TelnyxError,TELNYX_ERROR_CODES,TELNYX_WARNING_CODES,isMediaRecoveryErrorEvent. - Note
SESSION_NOT_REATTACHEDis an error, not a warning: in v2.26.0+ it isTELNYX_ERROR_CODES.SESSION_NOT_REATTACHED(48501) ontelnyx.error(fatal), not a warning.UNKNOWN_REATTACHED_SESSION(35002) is the separate warning.