Appearance
Errors
Errors can originate at three layers. The layer is easy to tell apart: gateway errors are non-200 HTTP with a plain message/error JSON body; RPC-proxy errors are a JSON-RPC error object (usually on HTTP 200 — the exceptions below carry a meaningful status too); chain errors are whatever the node itself returns (also HTTP 200 on JSON-RPC chains).
Gateway layer (HTTP status ≠ 200, plain JSON body)
| HTTP | When | Body |
|---|---|---|
401 | Missing or unknown apikey header | {"message":"No API key found in request"} / {"message":"Unauthorized"} |
402 | Tenant suspended | {"message":"account suspended — contact your administrator"} |
403 | debug_* method on /eth | {"error":"debug methods not permitted"} |
429 | Plan rate limit exceeded | {"message":"API rate limit exceeded"} + Retry-After |
429 | /eth heavy-method guard (1/min) | {"message":"Heavy method rate limit: 1/min for eth_getLogs"} + Retry-After |
RPC-proxy layer (JSON-RPC error object)
The full catalog of platform error codes:
| Code | HTTP | Message | Meaning / what to do |
|---|---|---|---|
-32700 | 200 | invalid JSON-RPC request | Body isn't valid JSON — fix the request |
-32600 | 413 | batch too large: N items exceeds the 100-item limit | Split the batch — the whole batch is rejected, nothing was executed (limits) |
-32011 | 200 | chain "xyz" not in project scope | The project's chains allow-list excludes this chain — adjust the project or use the right key |
-32012 | 401 | API key revoked | The key was revoked — it dies within seconds of the revocation, before anything runs (a batch is refused whole). Create/use a valid key |
-32005 | 200 | compute unit quota exceeded | Daily CU budget exhausted — wait for the window or upgrade (Compute Units) |
-32029 | 429 | heavy method rate limit exceeded for your plan, retry later | Per-plan heavy-method budget spent — honor Retry-After (Rate limits) |
-32601 | 200 | chain not available at this location: xyz | This deployment doesn't serve that chain — pick a location that does, or check the chain slug |
-32603 | 200 | backend request failed | All nodes for the chain are unreachable — retriable; alert us if persistent |
-32603 | 200 | unexpected backend response format | You sent a batch to a chain that isn't JSON-RPC (e.g. an array POSTed to /cosmos, which is REST) — not retriable, use the chain's real protocol |
-32603 | 200 | no response for request id in batch | The node answered the batch but returned nothing for that id — retry that item alone |
-32700 | 200 | failed to read request | The request body couldn't be read (client disconnect, truncated upload) — distinct from invalid JSON-RPC request |
A chain with no route answers from Kong, not the proxy
-32601 chain not available at this location means the gateway has a route for that chain but no node serves it here. A path with no route at all — a typo, or a chain this platform doesn't expose — never reaches the proxy and comes back as a gateway 404 instead:
json
// HTTP 404
{"message":"no Route matched with those values","request_id":"…"}Tell them apart by shape: a JSON-RPC error object = the chain is known; {"message":"no Route matched…"} = check the path against Endpoints.
Example:
json
{"jsonrpc":"2.0","error":{"code":-32011,"message":"chain \"bsc\" not in project scope"},"id":1}Inside a batch
A batch is rejected whole only for -32700 (unparseable), -32600 (too large), -32011 (chain scope) and -32012 (revoked key). The heavy-method budget (-32029), -32601 and backend failures (-32603) are applied per item: the response arrives as HTTP 200 and affected items carry their own error object while the rest of the batch executes normally.
REST-style chains
REST chains (TRON, Aptos, Stellar, TON's GET form) translate the same conditions to HTTP codes instead:
| HTTP | Body |
|---|---|
401 | {"error":"API key revoked"} |
403 | {"error":"chain ... not in project scope"} |
404 | {"error":"chain not available at this location: ..."} |
502 | {"error":"backend request failed"} |
WebSocket handshakes
wss://…/ws/<chain> authenticates the HTTP upgrade exactly like an HTTPS call, so failures surface as handshake status codes: 401 (bad key), 403 (chain scope), 404 (chain has no WS endpoint or isn't served here), 429 (handshake rate) — see WebSockets.
Chain layer (the node speaks)
Passed through verbatim. The common ones:
| Chain family | Example | Meaning |
|---|---|---|
| EVM | {"code":3,"message":"execution reverted"} | Contract reverted your eth_call/estimateGas |
| EVM | {"code":-32000,"message":"nonce too low"} | Transaction nonce already used |
| EVM / JSON-RPC | {"code":-32601,"message":"Method not found"} | The node doesn't expose that method — distinguish from the platform's -32601 by the message text |
| bitcoind | {"code":-5,"message":"No such mempool or blockchain transaction"} | Unknown txid (use a valid one or add blockhash) |
| bitcoind | {"code":-22,"message":"TX decode failed"} | sendrawtransaction payload isn't valid hex tx |
| bitcoind (BCHN) | {"code":-32601,"message":"Method not found"} | e.g. estimatesmartfee on Bitcoin Cash — use estimatefee |
| rippled | {"result":{"error":"actNotFound"}} | Account not on ledger (rippled errors live inside result) |
| NEAR | {"error":{"cause":{"name":"UNKNOWN_ACCOUNT"}}} | Account doesn't exist |
Retry matrix
| Condition | Retry? | How |
|---|---|---|
429 + Retry-After (plan limit or -32029) | yes | wait exactly Retry-After, then once |
-32603 backend request failed | yes | exponential backoff with jitter, ≤3 attempts |
5xx from gateway | yes | exponential backoff with jitter |
-32700, -32011, -32601 | no | fix the request/key/project |
-32600 batch too large | no | split into ≤100-item batches and resend |
-32012 key revoked | no | switch to a valid key |
-32005 quota | no (today) | resumes after the 24 h window |
401/402/403 | no | fix credentials / account / method choice |
| Chain-level errors (revert, nonce, decode) | no | application logic, not transport |
A ready-made backoff implementation lives in Batches, retries & caching.
Correlating with support
Every response carries X-Correlation-ID. Include it when you open a ticket — it pins your request across gateway and proxy logs.