Error Handling

Classify errors by protocol before choosing a retry.

HTTP and JSON-RPC

SignalMeaningYour action
HTTP 400Invalid HTTP requestFix the request
HTTP 401Missing or invalid keyReplace the credential
HTTP 429Request limit reachedBack off
HTTP 500Server processing failedRetry with a limit
HTTP 503Service unavailableRetry with backoff
JSON-RPC -32601Unknown methodFix the method
JSON-RPC -32602Invalid parametersFix 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

StatusYour action
UNAUTHENTICATEDCheck metadata
PERMISSION_DENIEDCheck plan or policy
INVALID_ARGUMENTFix request fields
NOT_FOUNDRefresh the topic catalog
RESOURCE_EXHAUSTEDReduce concurrent work
UNAVAILABLEReconnect with backoff
INTERNALRetry 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.