Errors & troubleshooting
Prism returns standard JSON-RPC errors. Codes originating at the edge are distinguishable from ones passed through from a provider.
HTTP status codes
| Status | Cause | Fix |
|---|---|---|
200 | Request handled - check the body for a JSON-RPC error | Inspect error in the response |
400 | Malformed JSON or invalid envelope | Validate the body before sending |
401 | Key missing, malformed or revoked | Check the last path segment of your URL |
403 | Origin not allowed for this key | Add the origin, or use a server-side key |
413 | Body over 10 MB | Split the batch |
429 | Rate limit exceeded | Honour Retry-After; see rate limits |
503 | No healthy upstream in the pool | Back off; check status |
A JSON-RPC error arrives with HTTP 200 - that is the protocol working as specified, not a success. Always check the body.
JSON-RPC error codes
| Code | Message | Meaning |
|---|---|---|
-32700 | Parse error | The body was not valid JSON |
-32600 | Invalid request | Envelope missing jsonrpc, method or id |
-32601 | Method not found | Unsupported, or not on this key's allowlist |
-32602 | Invalid params | Wrong count or type for the method |
-32603 | Internal error | Includes "no healthy upstream" - see below |
-32005 | Limit exceeded | Rate limit, or a query range past its cap |
3 | Execution reverted | Your contract call reverted - a correct answer |
Common problems
"Execution reverted" with no reason
The contract reverted. This is not a Prism failure and is not retried, because retrying produces the same answer.
Decode the revert data rather than guessing:
import { decodeErrorResult } from 'viem';
try {
await client.readContract({ address, abi, functionName: 'transfer', args });
} catch (error) {
if (error.data) {
console.log(decodeErrorResult({ abi, data: error.data }));
}
}If it reverts at latest but not at an older block, your call depends on state that changed - a balance, an allowance, a pause flag.
"No healthy upstream available"
Every provider's breaker is open. Prism fails fast rather than burning your deadline.
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "No healthy upstream available",
"data": { "providersOpen": 5, "retryAfterMs": 4000 }
}
}Back off for retryAfterMs, then retry once. Check status - a whole pool opening at once usually means a network-wide event rather than a provider one.
Query returned more than 10,000 blocks
eth_getLogs is capped at 10,000 blocks and 50,000 logs per request. Split the range - see JSON-RPC methods for a chunking helper.
Nonce too low
Two submissions used the same nonce. Prism does not manage nonces and never resubmits a transaction, so this is almost always an application-side race: two workers reading eth_getTransactionCount at the same moment.
Serialise submissions per sending address, or track the nonce yourself and increment locally after each submission.
Getting 429 well under my limit
Three usual causes:
- Batches count per entry. A batch of 20 costs 20 requests, not one.
- The limit is per second, not averaged. A burst of 300 in one second exceeds a 250/s limit even at low daily volume.
- A key is shared. Staging and production on the same key share one bucket. Split them.
Latency higher than expected
Check X-Prism-Upstream-Latency against X-Prism-Total-Latency. If upstream is high, the pool is slow - visible on the playground. If total is much higher than upstream, the time is in your network path to our edge, not in routing.
Also check X-Prism-Attempts: a value above 1 means a failover happened, which costs a round trip.
Results appear stale
Reads at latest are cached for two seconds. If you need to observe a write immediately, read at an explicit block number returned by the receipt, rather than at latest.
If state seems to move backwards, that would be a consistency bug on our side, not yours - the high-water mark exists to prevent it. Send us the request ID.
WebSocket keeps disconnecting
Sockets idle for 10 minutes with no active subscriptions are closed. Keep one subscription open, or send a periodic request.
If it drops sooner, check that you are not exceeding 20 concurrent sockets per key - a service that reconnects without closing the old socket exhausts that quickly.
Getting help
Include the X-Prism-Request-Id from the failing response. It lets us find the exact request, the provider it went to, and the routing decisions around it.
Email hello@prismrpc.co, or security@prismrpc.co for anything sensitive.
