Errors and troubleshooting
Handle RealtimeError, know which errors the SDK retries for you, and fix the most common setup problems.
Every failure the SDK reports is a RealtimeError, whether it came from the node or was caught locally before
anything was sent.
import { Code, isRealtimeError } from '@folkways/realtime';
try {
await client.topic('chat/lobby').publish('message', { text: 'hi' });
} catch (err) {
if (isRealtimeError(err) && err.code === Code.Forbidden) {
showError("You can't post in this room");
} else {
throw err;
}
}| Field | Meaning |
|---|---|
code | A number from Code, e.g. Code.Forbidden (203) |
codeName | The code's name, e.g. 'Forbidden' |
message | What went wrong, including the topic when there is one |
retry | What may help: 'never', 'backoff' (try again later), 'after-reauth' (with a new token) or 'reconnect' |
retryAfterMs | How long the node asked you to wait, when it did |
topic | The topic the error is about, when there is one |
local | true when the SDK raised it without asking the node, e.g. a bad topic name |
The SDK already retries what can be retried: reconnects, token refreshes, rate-limited publishes and server errors. The errors you see are the ones it couldn't fix.
Where errors show up
| Where | What |
|---|---|
await client.connect() | Fatal connection errors, or Timeout while it keeps trying |
await topic.publish() | That publish's failure |
sub.ready and sub.on('error') | The subscription was refused or failed, or your handler threw |
sub.on('ended') | The node ended the subscription, e.g. after permissions narrowed |
client.connection.on('error') | Everything else: failed token refreshes, dropped outbox entries, errors in your listeners |
client.connection.error | Why the connection is failed |
Common problems
| You see | Usually means | Fix |
|---|---|---|
AuthRequired | Your token endpoint failed or returned no token | Check the endpoint answers 200 with { "token": "…" } for a signed-in user |
AuthInvalid | The node can't verify the token | The kid must be one of the segment's signing keys and match its algorithm; seg must be this segment's ID; the token must live at most 15 minutes. For a publishable key: it was revoked or expired, or anonymous connections are off |
AuthExpired | The token ran out and couldn't be refreshed | Use authUrl or a token function, not a fixed string. Check your server's clock |
Forbidden | The token or the topic rule doesn't allow this | The topic must match both the token's capabilities and a rule that allows the operation |
ClassMismatch | The delivery type doesn't match the topic's rule | Pass delivery: 'kv' or 'signal' to match the rule's class, or publish to a topic whose rule has that class |
InvalidTopic | Bad topic name | Use only A-Z a-z 0-9 . _ ~ : @ = + - in each level |
Suspended | The segment is turned off, the workspace's subscription ended, or the publishable key is paused | Check the segment's Settings and the workspace's Billing |
QuotaExceeded | A segment limit was reached: connections, topics or messages | Raise the limit in Settings or upgrade the plan |
RateLimited | Over the publish rate (100 per second per connection by default) | The SDK retries; slow down if it persists |
PayloadTooLarge | The payload is over session.limits.maxPayloadBytes | Send less, or a reference to the data |
Replaced | The same user connected from too many devices; this one was closed | Show "signed in elsewhere"; reconnect only when the user asks |
SegmentMismatch | connect({ segment }) got a token for another segment | Check which environment's backend issued the token |
NotConnected | The client has been offline for over 2 minutes | Wait for connected, or use a persistent store to queue |
Timeout | No answer in time | For connect(): it keeps trying in the background |
Turn on logs to see what the SDK is doing (tokens are never logged):
import { consoleLogger } from '@folkways/realtime';
new Folkways.Realtime({ url, authUrl, logger: consoleLogger('debug') });The full list of codes is in the error code reference.