Errors & troubleshooting
Failures split into two phases: before the WebSocket opens (HTTP status on upgrade) and after connect (JSON error frames sent by the server).
Upgrade errors
These HTTP responses are sent before the WebSocket handshake completes. No WebSocket frames are exchanged.
- 401 — invalid or missing
apiKey. - 403 — key authenticated but not entitled for WebSocket / package access (JSON body with an
errorreason). - 429 — too many open WebSocket connections for your account (or global capacity). Body:
{ "error": "WS_CONNECTION_LIMIT_EXCEEDED", "message": "rate limit exceeded" }. Close an existing connection or upgrade your package. See Rate limits. - 503 — auth or entitlement check timed out / temporarily unavailable. Response includes
Retry-After: 2; retry shortly. The same status with a JSON body carryingSERVICE_RESTARTINGandRetry-After: 1is returned for a few seconds while a release swaps the serving process: reconnect after the delay and resubscribe. Treat any handshake answer other than101as a retry, whatever the status.
In-stream error codes
After connect, failed client actions emit type: "error" frames. Subscribe failures also set event: "subscribe_failed" (or subscribe_partial_failed). Invalid symbols appear in rejected when present — there is no details object.
| Parameter | Description |
|---|---|
| INVALID_PAYLOAD | Malformed JSON, non-object body, unknown action, bad channels array, missing channels, invalid symbols field type, or generic processing failure. |
| EMPTY_SYMBOLS | symbols field is present but empty after normalization. |
| TOO_MANY_SYMBOLS | More symbols in one subscribe action than the per-message cap (env API_PUBLIC_WS_MAX_SYMBOLS_PER_SUBSCRIBE, default 500). Message is usually "rate limit exceeded". |
| SYMBOL_LIMIT_EXCEEDED | Account distinct-symbol cap or per-connection distinct symbol cap. Message is usually "rate limit exceeded". |
| UNSUPPORTED_CHANNEL | Channel string is not one of the 13 public channels. |
| INVALID_CHANNEL | Channel is known but not allowed for this API key (entitlement / package deny). |
| INVALID_SYMBOL | One or more symbols are not enabled for the requested channel. See rejected[] (and optional channel / symbol fields). |
| UNSUPPORTED_SYMBOL_FOR_CHANNEL | Symbol is known but not valid for the requested channel asset class. |
| UNAUTHORIZED_SYMBOL | Symbol is not entitled for this account on that channel. |
| PARTIAL_SUBSCRIBE_FAILED | Some symbols subscribed successfully; rejected[] lists those that did not (event: subscribe_partial_failed). |
| MARKET_DATA_CAPACITY | Temporary capacity / activation limit for demand-driven (smart-auto) symbols. Retry later. |
| PACKAGE_EXPIRED | In-stream entitlement revoke after connect (package ended). Connection may be closed. |
The server also sends native WebSocket ping frames. If the client does not answer with pongs, the server emits a system { "event": "disconnect", "code": "HEARTBEAT_TIMEOUT" } and closes with code 4008.
When a release replaces the serving process, every open stream first receives { "event": "disconnect", "code": "SERVER_RESTART" } and is then closed with code 1012. Reconnect right away and resubscribe; the snapshot on subscribe closes the gap. A close that arrives with no system frame and no close code (1006) was not initiated by the server and usually points at a reset on the network path; reconnect the same way.
Common fixes
Start here when a connection fails or subscribe actions return errors:
- Check the connect URL — use
wss://stream.tickerlayer.com/?apiKey=..., not the REST base URL. URL-encode your key withencodeURIComponent. See Connection and Authentication. - Wait for the ready frame — send subscribe actions only after the server emits
event: "ready". - Send valid JSON text frames — one JSON object per message; binary frames are not accepted from the client.
- Verify symbols and channels — use symbols from the REST symbol list for that asset class (for example
GET /stocks/symbolsfor Stocks). For equities, use market-qualified symbols such asUS:AAPL. Subscribe only to channels included in your package. - Respect connection and symbol limits— close unused connections before opening new ones and stay within your plan's distinct-symbol allowance. The per-subscribe symbol count is a separate server cap (default 500). See Rate limits.
REST quota errors are documented separately on Errors and Rate limits.