Skip to main content
RPC operator referenceHTTPS / WSS · JSON-RPC 2.0

Error reference

Machine-readable gateway and JSON-RPC errors, their billing behavior, and the next action to take.

WebSocket upgrades use HTTP authorization and availability status codes. After connection, method errors use JSON-RPC responses. Explicit socket closes identify revocation, unavailable native sources, rate exhaustion or a slow reader. Reconnect with backoff, resubscribe and reconcile missed blocks. See WebSocket errors and recovery.

Three sources, two response shapes

HTTP-layer rejections generated by the authenticated gateway use a top-level JSON envelope. error is the backward-compatible short label, code is a stable machine-readable string,message explains the failure, resolution gives the next action, and documentation_url points to the controlling reference. Quota and limit errors can add fields such as used, limit, or requiredTokens.

JSON-RPC protocol and gateway-policy failures keep the JSON-RPC 2.0 shape. Their numeric code and message live in error, while SolidRPC's actionable resolution and documentation_url live in error.data. Errors returned by a blockchain node pass through unchanged and may not contain those two guidance fields.

Gateway rejections never reach a node and are never billed. Proxy or upstream HTTP 5xx failures are also never billed. A node-returned JSON-RPC error normally arrives with HTTP 200 and consumes one response unit because the node performed the method call. Check the HTTP status first, then inspect either the top-level string code or the numeric error.code. The complete request and response contract is published in the SolidRPC OpenAPI 3.1 contract.

Gateway errors

400 malformed JSON-RPC request

Invalid JSON returns a JSON-RPC parse error:

Example
{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32700,
    "message": "Parse error",
    "data": {
      "resolution": "Send syntactically valid JSON with Content-Type: application/json.",
      "documentation_url": "https://solidrpc.io/docs/errors"
    }
  }
}

Empty batches, objects without a method, and batches without any valid method return an invalid-request error:

Example
{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32600,
    "message": "Invalid Request",
    "data": {
      "resolution": "Send a JSON-RPC 2.0 object with a non-empty method, params, and request id.",
      "documentation_url": "https://solidrpc.io/docs/errors"
    }
  }
}

On the clean /evm/{chainId} route, sending both X-API-Key and Authorization: Bearer YOUR_API_KEY is ambiguous and returns:

Example
{
  "error": "Conflicting API key sources",
  "code": "conflicting_api_key_sources",
  "message": "Conflicting API key sources",
  "resolution": "Send either Authorization: Bearer YOUR_API_KEY or X-API-Key: YOUR_API_KEY, not both.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

This check runs before authentication and rate limiting, so a conflicting request consumes nothing. Pick one transport.

Malformed JSON-RPC requests consume one rate-limit token to prevent abuse, but they never consume quota or appear as billed usage. Valid JSON is accepted even when the content type is missing or not application/json, although clients should continue sending Content-Type: application/json. Payloads over 5 MB return HTTP 413 and are also free.

401 missing or invalid authentication

Example
{
  "error": "Missing or invalid API key",
  "code": "invalid_api_key",
  "message": "Missing or invalid API key",
  "resolution": "Send a valid SolidRPC API key using a documented URL or header authentication form.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

The URL key is absent or malformed, or the clean endpoint has no valid Bearer API key or X-API-Key header. Check either https://rpc.solidrpc.io/YOUR_API_KEY/evm/{chainId} or https://rpc.solidrpc.io/evm/{chainId} with one supported API-key header. Do not retry. Fix the credential.

If the code is management_credential_on_rpc, you supplied an sa_ management credential. Use it only on the agent management API. RPC calls require a separate ak_ key. See the agent setup guide.

When a key requires JWT authentication, a missing, malformed, expired, or otherwise invalid Bearer token returns the same generic JWT error with the standard challenge header:

Example
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer

{
  "error": "Missing or invalid JWT",
  "code": "invalid_customer_jwt",
  "message": "Missing or invalid JWT",
  "resolution": "Send a valid customer-signed Bearer JWT that satisfies the API key's configured issuer, audience, lifetime, and scopes.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

A JWT-required key must use the URL-key form plus a Bearer JWT, or X-API-Key: YOUR_API_KEY plus the Bearer JWT. A Bearer API key alone cannot satisfy both credentials.

Check the signature, server-generated kid, fixed audience, issuer, and numeric time claims. See API key security.

402 quota exceeded

You used all response units in your plan, and overage billing is not enabled. Further RPC calls are blocked at the quota unless overage billing is enabled. On a monthly (paid) plan:

Example
{
  "error": "Monthly response quota exceeded",
  "used": 10000000,
  "limit": 10000000,
  "code": "monthly_quota_exceeded",
  "message": "You have used all responses included in your plan. Upgrade to continue.",
  "resolution": "Wait for the billing-period reset, upgrade the plan, or enable overage billing when eligible.",
  "documentation_url": "https://solidrpc.io/docs/pricing"
}

On the Free plan the quota is daily:

Example
{
  "error": "Daily response quota exceeded",
  "used": 10000,
  "limit": 10000,
  "window": "day",
  "code": "daily_quota_exceeded",
  "message": "You've used all responses included in your plan for today. Your quota resets at 00:00 UTC. Upgrade to a paid plan for a monthly quota and higher limits.",
  "resolution": "Wait until 00:00 UTC, upgrade the plan, or use an eligible paid plan with overage enabled.",
  "documentation_url": "https://solidrpc.io/docs/pricing"
}

Do not retry a 402, it stays a 402 until your quota resets (00:00 UTC on Free, your billing date on paid plans), you upgrade, or you enable overage.

Active PAYG has no request quota and does not return 402 for usage volume. If a PAYG charge fails, PAYG is removed immediately and the account returns to its effective fallback, usually Free. That fallback can then return its normal 402. Resolve every PAYG invoice in Stripe before trying to enroll again. Payment restores eligibility but never silently reactivates PAYG.

403 invalid key, subscription, or policy denial

Example
{
  "error": "Invalid API key or inactive subscription",
  "code": "api_key_forbidden",
  "message": "Invalid API key or inactive subscription",
  "resolution": "Check that the API key is active and belongs to an account with an active subscription.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

The key looks valid but doesn't resolve to active access: it is unknown, revoked, or the account has no effective Free, paid-plan, or PAYG entitlement. Check the key and Billing in the dashboard. Do not retry.

Arc Mainnet (chain ID 5042) also returns 403 to Free accounts and keyless aliases. Use a personal API key on a paid plan or active PAYG; Arc Testnet remains available on Free.

Example
{
  "error": "Arc Mainnet requires a paid plan or active PAYG",
  "code": "paid_network_required",
  "message": "Arc Mainnet requires a paid plan or active PAYG",
  "resolution": "Upgrade to a paid plan or activate PAYG, then retry with your personal API key. Arc Testnet remains available on Free.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

A valid API key and JWT can also be denied when the verified source, chain, or any method in the request is outside the effective key/token policy:

Example
{
  "error": "Request denied by API key policy",
  "reason": "method_denied",
  "code": "api_key_policy_denied",
  "message": "Request denied by API key policy",
  "resolution": "Use a source, chain, and method allowed by the API key and delegated token policy.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

The bounded reason is one of route_denied, source_unverified, source_denied, chain_denied, or method_denied. Policy denials never consume quota or billed usage.

404 unknown route and 405 wrong HTTP method

Unknown gateway paths return a structured JSON 404 instead of HTML. Its documentation_url points directly to the machine-readable OpenAPI contract:

Example
HTTP/1.1 404 Not Found

{
  "error": "API route not found",
  "code": "api_route_not_found",
  "message": "API route not found",
  "resolution": "Use a documented POST endpoint from the SolidRPC OpenAPI contract.",
  "documentation_url": "https://solidrpc.io/openapi.json"
}

The clean /evm/{chainId} route accepts only HTTPS POST. Other methods return HTTP 405, set Allow: POST, and use the same gateway envelope with code method_not_allowed. An unavailable chain on the keyless public route is different: it returns a JSON-RPC error whose guidance remains inside error.data.

429 rate limit exceeded

Example
{
  "error": "Rate limit exceeded",
  "requiredTokens": 1,
  "availableTokens": 0,
  "code": "rate_limit_exceeded",
  "message": "Rate limit exceeded",
  "resolution": "Wait for Retry-After seconds, then retry with exponential backoff and jitter.",
  "documentation_url": "https://solidrpc.io/docs/rate-limits"
}

Your account's token bucket is empty (batches need one token per method call, all at once). A recoverable 429 includes a Retry-After delay:

Example
HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-RateLimit-Limit: 120
X-RateLimit-Burst: 600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 5

Wait for that delay, then retry with exponential backoff plus jitter. If the batch exceeds X-RateLimit-Burst, the header is omitted because the batch must be split. See rate limits. Never billed.

A 429 whose body is a JSON-RPC error with code -32005, instead of the envelope above, means SolidRPC is briefly at capacity for large responses. It is not your account limit, it carries Retry-After: 1, and it is never billed:

Example
HTTP/1.1 429 Too Many Requests
Retry-After: 1

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32005,
    "message": "capacity exceeded, retry later"
  }
}

Retry after the delay with exponential backoff plus jitter. Inside a batch only the affected calls carry the -32005 error, and the batch keeps HTTP 200 and its usual billing.

Repeated invalid JWT verification attempts use a separate abuse bucket and can return:

Example
HTTP/1.1 429 Too Many Requests
Retry-After: 1

{
  "error": "JWT verification rate limit exceeded",
  "code": "jwt_verification_rate_limit_exceeded",
  "message": "JWT verification rate limit exceeded",
  "resolution": "Wait for Retry-After seconds before submitting another JWT verification attempt.",
  "documentation_url": "https://solidrpc.io/docs/api-key-security"
}

5xx temporary service, upstream, or proxy transport failure

When the gateway cannot complete its proxy connection, it returns the structured gateway envelope: HTTP 502 with upstream_bad_gateway for an invalid upstream HTTP response, HTTP 503 with upstream_capacity when no upstream connection became free in time, HTTP 504 with upstream_timeout for a reset, DNS, connection, or timeout failure, and HTTP 500 with proxy_internal_error for an unclassified internal proxy failure. These responses include Retry-After: 1and never echo the requested host, path, or API key.

Example
HTTP/1.1 504 Gateway Timeout
Content-Type: application/json; charset=utf-8
Retry-After: 1

{
  "error": "Upstream request timed out",
  "code": "upstream_timeout",
  "message": "Upstream request timed out",
  "resolution": "Wait one second, then retry with exponential backoff. Contact SolidRPC support if the error persists.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

A 503 with upstream_capacity means the request waited too long for a free upstream connection during a load spike and was refused before it was sent, so no work was done for it. It is temporary and does not indicate a problem with your API key: honor Retry-After and retry with exponential backoff plus jitter. Like every HTTP 5xx, it is never billed.

Example
HTTP/1.1 503 Service Unavailable
Content-Type: application/json; charset=utf-8
Retry-After: 1

{
  "error": "Upstream capacity is temporarily exhausted",
  "code": "upstream_capacity",
  "message": "Upstream capacity is temporarily exhausted",
  "resolution": "Wait one second, then retry with exponential backoff. Contact SolidRPC support if the error persists.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

A server that successfully returns its own HTTP 5xx response is different: the proxy passes that status and body through unchanged. That upstream body can be JSON-RPC or another JSON error shape and is not guaranteed to contain SolidRPC's resolution or documentation_url. A 504 can also mean the upstream method budget was exhausted, 30 seconds for standard methods and 45 seconds for trace/debug (see tracing).

Every HTTP 5xx is free: its quota reservation is refunded and it cannot generate overage, although it remains visible in error and latency analytics. Rate-limit tokens are not refunded, which prevents retry storms. Honor Retry-After when present and retry with exponential backoff plus jitter. A heavy trace that repeatedly returns 504 needs a narrower query, not unlimited retries.

Advanced key policies fail closed only while a security policy change is being applied to the key, which lasts milliseconds:

Example
HTTP/1.1 503 Service Unavailable
Retry-After: 1

{
  "error": "API key security policy is being updated",
  "code": "api_key_policy_updating",
  "message": "API key security policy is being updated",
  "resolution": "Wait for Retry-After seconds, then retry the same request.",
  "documentation_url": "https://solidrpc.io/docs/errors"
}

Retry this temporary 503 with backoff. It is never billed and does not indicate an upstream blockchain-node failure. A fault in our own rate-limit or quota infrastructure never produces an error response: the gateway keeps serving your requests on per-instance enforcement until the shared state recovers.

Blocked methods

Methods on the gateway denylist (node and consensus control, including txpool_*, see the method policy) return HTTP 200 with a JSON-RPC -32601 error and are never billed. The same applies to the few calls some networks cannot answer, which SolidRPC refuses itself: debug_storageRangeAt on Arbitrum One (42161), Robinhood Chain (4663) and their testnets, and the arbtrace_* namespace on Robinhood Chain, whose traces exist only for Arbitrum One's legacy blocks (-32601, data.reason method_unavailable_on_network), debug_accountRange at any block on Ethereum, Avalanche C-Chain, Base, Optimism, Arc Mainnet, Unichain, World Chain and Arc Testnet (the same -32601), eth_getProof at a block behind the recent window (no more than 96 behind the chain head, with earliest, safe and finalized resolved to block numbers and judged the same way) on Ethereum, BNB Smart Chain, Base, Arbitrum One, Optimism, Robinhood Chain, Arc Mainnet, Polygon PoS, Unichain, World Chain, Arbitrum Sepolia and Arc Testnet and debug_accountRange behind that window on BNB Smart Chain, Arbitrum One, Robinhood Chain, Polygon PoS and Arbitrum Sepolia (-32602, historical_state_unavailable), and a state override naming the ArbOS state address 0xa4b05fff…ffff in eth_call, eth_estimateGas, eth_createAccessList, debug_traceCall or eth_simulateV1 on those four networks (-32602, state_override_not_allowed). Methods that only local development nodes implement, the anvil_*, hardhat_* and evm_* namespaces that development tooling sends to detect a local Anvil or Hardhat node, are refused the same way on every network (-32601, dev_node_method_unavailable). A batch is refused this way only when every entry in it is unservable. Inside a batch with serviceable siblings, on Arbitrum One, Robinhood Chain and Robinhood Testnet SolidRPC answers each unservable entry individually with the same error, billed like any answered call and never counted toward the SLA (state overrides and development-node methods are not answered this way, so such an entry is still forwarded), while on Ethereum, BNB Smart Chain, Base, Optimism, Arc Mainnet, Polygon PoS, Unichain, World Chain, Arbitrum Sepolia, Arc Testnet and Avalanche C-Chain such a batch is forwarded whole and its unservable entries are answered with the network's own error, billed, and can count toward the SLA. The request ID is preserved for a single call, and SolidRPC guidance is placed in error.data:

Example
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "method admin_peers is not supported",
    "data": {
      "resolution": "Use a supported read, trace, or debug method that does not control the node or consensus layer.",
      "documentation_url": "https://solidrpc.io/docs/errors"
    }
  }
}

An eth_getLogs call whose block range is wider than the network's limit is refused the same way: HTTP 200, JSON-RPC -32602, data.reason log_range_limit, never billed. The message states the limit and suggests a range starting at your fromBlock that will succeed, in the form most indexers re-chunk on automatically, and data.maxBlockRange carries the limit. Each network's limit is listed on its chain page. A blockHash filter and a range ending at safe or finalized are not checked, and a batch is refused only when every call in it is over the limit. The limit bounds the block range only. A log-dense query inside it can still pass the response size limit below, so narrow the range or the filter.

Response size limit

A method call over HTTPS whose response would exceed 150 MB (150,000,000 bytes) of uncompressed JSON returns HTTP 200 with JSON-RPC -32020. data.reason is response_too_large and data.maxResponseBytes carries the limit. The message itself is the guidance, and the error carries no resolution or documentation_url field:

Example
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32020,
    "message": "Response size limit exceeded. Narrow the block range or add an address or topic filter.",
    "data": {
      "reason": "response_too_large",
      "maxResponseBytes": 150000000
    }
  }
}

Do not retry the same call. It returns the same error. Split the block range or add an address or topic filter. The call is billed as one response unit, because the query ran before the limit stopped it. In a batch only the oversized call gets this error. See rate limits for how this limit meets the eth_getLogs block range. The keyless public endpoints use the same code for their lower 2 MB limit.

Over WebSocket the limit is 16 MiB (16,777,216 bytes) per response, and a batch counts as one response. A larger response gets JSON-RPC -32603 with the message RPC request refused or unavailable and no data field. A batch over the limit gets that single error with id: null. The same error covers other WebSocket calls that could not be served, so retry a large query over HTTPS rather than on the socket. See WebSocket.

Node-passthrough errors

Execution reverts (code: 3), -32602 (invalid params), -32000-range client errors, and a node's own -32601 for methods its client doesn't implement all pass through unchanged with HTTP 200. These method calls reached the nodes and did the work, so each consumes 1 response unit like any other billable call. One exception: on Arbitrum One (42161) and Robinhood Chain (4663) SolidRPC answers net_listening itself rather than passing the chain's own -32601 through — see method availability for what that means and why net_peerCount is not answered. Treat a node's error.data as method- and client-specific. Unlike gateway-produced JSON-RPC errors, it is not guaranteed to include resolution or documentation_url. Where a client defines it, error.data carries the node's own payload — an eth_call revert, for example, returns the ABI-encoded revert reason as a hex string:

Example
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": 3,
    "message": "execution reverted: ERC20: transfer from the zero address",
    "data": "0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000254552433230..."
  }
}

SolidRPC's internal routing is not part of the API contract. Which upstream served a call, and how many attempts, retries, or hedges it took, are not returned in error.data or in a response header, and should not be branched on. Per-chain behavior that is contractual — history windows, and which method families a chain serves — is documented per network in the network catalog. To investigate a specific slow or failed request, keep its timestamp, chain, and method: those identify it.

Batch semantics

  • A batch containing any blocked method is rejected whole: one error object with id: null, nothing executed, nothing billed.
  • Gateway errors: 400, 401, 402, 403, 413, 429, apply to the whole batch.
  • An upstream HTTP 5xx applies to the whole batch and bills none of its entries.
  • A partially invalid batch reaches the node, only entries with a valid method consume rate-limit and quota units.
  • Node-level errors are per-entry: one revert doesn't fail the rest of the batch, and every entry that reached the nodes is billed.
  • Over HTTPS the response size limit applies to each entry: an oversized entry gets -32020 and the rest of the batch is served. Over WebSocket the 16 MiB limit covers the whole batch response, and a batch over it gets one -32603 error.

Quick reference

StatusMeaningBilledRetry?
200 (result)Successful responseYes—
200 + -32601 (blocked)Method blocked by gateway policyNoNo
200 + JSON-RPC errorNode-level error (revert, bad params, …)YesDepends on the error
200 + -32020HTTPS response would exceed 150 MBYesNo, split the range or narrow the filter
400Invalid JSON/JSON-RPC or conflicting API-key headersNoNo, fix the request
401Missing or malformed API key, or missing/invalid required JWTNoNo, fix the key
402Quota exceeded, overage not enabledNoNo, upgrade, enable overage, or wait for reset
403Unknown/revoked key, inactive subscription, policy denial, or paid-only networkNoNo
404Unknown API route or unavailable public chainNoNo, use a documented route or chain ID
405The clean RPC route received a method other than POSTNoNo, send HTTPS POST
413Request body exceeds 5 MBNoNo, reduce the payload
429Rate limit exceeded, or SolidRPC briefly at capacityNoYes, with backoff
500–599Temporary security-state, rate-limit, upstream, or proxy transport failureNoYes, with backoff