Documentation

Errors and Troubleshooting

Catch operation failures, handle asynchronous server errors, and diagnose common SDK problems.

Before you start: follow Connection and lifecycle. Register an error handler once per channel, and also catch rejected operation promises.

1. Catch the operation you started

Use these patterns in web/app.js. The first replaces a publish handler's catch logic, and the second replaces the channel's error listener.

import { ConnectionError, textPayload } from "@useceleris/client";

try {
  await chat.publish({ payload: textPayload("Hello") });
} catch (error) {
  if (error instanceof ConnectionError && error.code === "NotConnected") {
    console.warn("Wait until connected before sending.");
  } else {
    console.error(error.name, error.message);
  }
}

Catch connect(), publish(), and presenceList() at their call sites. A failed initial connect rejects its caller and does not also fire onError. The SDK likewise reports a failed presence query to its caller.

2. Handle server errors separately

import { ServerError } from "@useceleris/client";

const stopErrors = channel.events().onError((error) => {
  if (error instanceof ServerError) {
    console.error(error.type, error.subType, error.message);
    switch (error.type) {
      case "PermissionDeniedError":
        console.warn(
          "Check the server-issued channel and segment permissions."
        );
        break;
      case "MessageSizeLimitError":
        console.warn("Reduce the payload size.");
        break;
      case "RateLimitError":
        // The SDK pauses and resends recent commands by itself.
        console.warn("Rate limited; reduce the publishing rate if this repeats.");
        break;
      default:
        console.warn("The server reported an error.");
    }
    return;
  }
  console.error(error.code, error.message);
});
// Later:
stopErrors();

A ServerError contains type, subType, message, and resource. It has no SDK code. Error types are open-ended, so retain a default branch for a newer server. A resource can be null, a string, a number, a bigint, or a nested array of these. Check its type before you use it. Numeric resources are not necessarily timestamps.

A permission denial can identify a command and segment. It does not identify which of several otherwise identical publishes caused the error. The SDK correlates presence-query errors internally. Those errors reject their query instead.

Server error text is for people, not for programs. Show it as text, never as raw HTML. Do not put sensitive diagnostic details in shared logs. Server errors leave the connection open.

3. Choose the right response

SDK codeResponse
ConfigurationFix invalid input or malformed credential output. A retry with unchanged input does not help
NotConnectedConnect the channel, then try again. While the channel is reconnecting, a publish waits in the queue, but a presence query rejects
TimeoutCheck the credential endpoint/network or query deadline
CancelledUsually an intentional abort or close. Do not automatically restart canceled work
TransportCheck network and credential setup. This does not prove an authentication failure
BackpressureSlow production. The publish queue (publishQueueSize, 64 by default) is full, or a presence query found the writer full or paused after a rate limit. Wait, then retry
OperationInProgressDo not start simultaneous connects or presence queries on one channel
DeliveryUnknownAcceptance is uncertain. Do not blindly resend an irreversible operation
ProtocolErrorOne frame was dropped. The connection remains usable

The SDK isolates a listener's synchronous exception and reports it as a safe listener failure. Catch errors in asynchronous work that your listeners start.

4. Diagnose common symptoms

SymptomFirst checks
First connect fails and nothing retriesThis is expected. Offer an explicit Retry action from failed
Socket connects but messages are absentChannel/segment match, a held subscription, and read permission
Sender sees no received copyallowEcho defaults to false
Publish resolves, then an error appearsExpected for server refusals. Resolution is only local acceptance
Presence events miss a userYou get events only for joins and leaves while you hold presence. Query a cluster-wide listing
The server denied credentials, but the error says TransportWebSocket handshake status is unavailable to the SDK
Messages are absent after recoveryReplay is bounded. Reload authoritative application state
Recovery stops in failedonError reports the cause. The SDK used all maximumReconnectAttempts, or the failure does not retry. Offer an explicit Retry
Presence request rejects with ConfigurationUse integer numbers: page 1–2147483647 and perPage 1–100. Do not pass strings or bigints
Arithmetic throws on mixed numeric typesCounts and page figures are numbers, and delivered timestamps are bigints. Do not mix them in arithmetic
JSON serialization throwsConvert bigint timestamps and bigint error-resource values to decimal strings. Keep counts as numbers
Closed channel cannot reconnectObtain a new channel handle

See Reconnection and Recovery for which failures retry and how the budget works. Do not implement your own retry timer while the channel is in the reconnecting state.

Use the numeric-value and JSON examples when you store SDK data. Number(timestamp) is not a general serialization fix. It can silently discard precision.

A publish call on an unconnected channel then reaches the NotConnected branch and sends nothing. The error listener handles server errors separately by type and does not parse their message.

Next: Server-side usage, or the Client API for the full error surface.

We use Google cookies for analytics and for advertising measurement, only if you allow them. Until you choose, Google sets no cookies. Refer to our Cookie Policy.