Error Handling
Classify errors by protocol before choosing a retry.
HTTP and JSON-RPC
| Signal | Meaning | Your action |
|---|---|---|
HTTP 400 | Invalid HTTP request | Fix the request |
HTTP 401 | Missing or invalid key | Replace the credential |
HTTP 429 | Request limit reached | Back off |
HTTP 500 | Server processing failed | Retry with a limit |
HTTP 503 | Service unavailable | Retry with backoff |
JSON-RPC -32601 | Unknown method | Fix the method |
JSON-RPC -32602 | Invalid parameters | Fix parameters |
javascript
async function rpc(method, params = []) {
const response = await fetch("https://api.mainnet-beta.solana.com", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.NODE_API_KEY,
},
body: JSON.stringify({
jsonrpc: "2.0",
id: crypto.randomUUID(),
method,
params,
}),
})
const body = await response.json()
if (!response.ok || body.error) {
throw new Error(body.error?.message ?? `HTTP ${response.status}`)
}
return body.result
}WebSocket
Treat an upgrade failure as an authentication or network error.
After a connected socket closes:
- Record the close code.
- Reconnect with backoff and jitter.
- Send every subscription again.
- Replace old subscription IDs.
- Read missed state through RPC.
gRPC
| Status | Your action |
|---|---|
UNAUTHENTICATED | Check metadata |
PERMISSION_DENIED | Check plan or policy |
INVALID_ARGUMENT | Fix request fields |
NOT_FOUND | Refresh the topic catalog |
RESOURCE_EXHAUSTED | Reduce concurrent work |
UNAVAILABLE | Reconnect with backoff |
INTERNAL | Retry once and record details |
Retry rules
- Add random jitter.
- Cap total attempts.
- Set deadlines.
- Do not retry permanent client errors.
- Keep transaction retries idempotent.
- Never log API keys.