{"record":{"id":"aaf5cf0e2f52bbb3","repo":"nautechsystems/nautilus_trader","slug":"eth-call-rpc-error-code","errorCode":null,"errorMessage":"eth_call RPC error {code}","messagePattern":"eth_call RPC error (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/http.rs","lineNumber":553,"sourceCode":"            .await\n            .map_err(|e| match e {\n                BlockchainRpcClientError::ClientError(message)\n                    if message.contains(\"redirect response rejected\") =>\n                {\n                    anyhow::anyhow!(\"eth_call redirect rejected\")\n                }\n                _ => anyhow::anyhow!(\"eth_call request failed\"),\n            })?;\n        let parsed = serde_json::from_slice::<RpcNodeHttpResponse<String>>(bytes.as_ref())\n            .map_err(|_| anyhow::anyhow!(\"Failed to parse eth_call response\"))?;\n\n        if parsed.jsonrpc.is_none()\n            && let (Some(code), Some(message)) = (parsed.code, parsed.message)\n        {\n            if eth_call_error_is_revert(code, &message) {\n                return Ok(RpcCallResult::Reverted);\n            }\n            anyhow::bail!(\"eth_call RPC error {code}\");\n        }\n\n        if let Some(error) = parsed.error {\n            if eth_call_error_is_revert(error.code, &error.message) {\n                return Ok(RpcCallResult::Reverted);\n            }\n            anyhow::bail!(\"eth_call RPC error {}\", error.code);\n        }\n        let value = parsed\n            .result\n            .ok_or_else(|| anyhow::anyhow!(\"eth_call returned no result\"))?;\n        let stripped = value.strip_prefix(\"0x\").unwrap_or(&value);\n        let bytes = hex::decode(stripped)\n            .map_err(|_| anyhow::anyhow!(\"Failed to decode eth_call response\"))?;\n        Ok(RpcCallResult::Success(Bytes::from(bytes)))\n    }\n\n    /// Estimates the gas required for a transaction via `eth_estimateGas`.","sourceCodeStart":535,"sourceCodeEnd":571,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/http.rs#L535-L571","documentation":"Raised by `call_result_at` when the RPC node responds to an `eth_call` with a bare JSON-RPC error object (top-level `code`/`message`, no `jsonrpc` field) that is NOT recognized as a revert by `eth_call_error_is_revert`. The library classifies revert-shaped errors as `RpcCallResult::Reverted`; anything else is an infrastructure/RPC-level failure surfaced with the numeric error code.","triggerScenarios":"Calling `call_at`/`call_result_at` against a node that returns a non-revert error: rate limiting (-32005), method not found (-32601), execution timeout (-32010), insufficient funds for gas, or node-level rejection not containing 'revert' in the message.","commonSituations":"Hitting a public RPC endpoint's rate limit; pointing at a node that doesn't support historical `eth_call` at old blocks (archive-mode required); load-balancer returning non-standard error bodies; gas price/cap rejected by the node.","solutions":["Inspect the reported JSON-RPC `code` and map it: -32005 rate limit → back off/retry; -32601 → check node capabilities.","Use an archive node if calling at historical blocks; execution reverted-at-genesis style errors on non-archive nodes look like this.","Add retry with backoff for transient codes (rate limit, timeout).","Verify the endpoint URL and that the provider supports `eth_call` with the block parameter used."],"exampleFix":"// before\nlet out = rpc.call_at(from, to, value, data, block).await?;\n// after\nlet out = match rpc.call_at(from, to, value, data, block).await {\n    Ok(out) => out,\n    Err(e) if e.to_string().contains(\"RPC error -32005\") => {\n        tokio::time::sleep(BACKOFF).await;\n        rpc.call_at(from, to, value, data, block).await?\n    }\n    Err(e) => return Err(e),\n};","handlingStrategy":"retry","validationCode":"// Check endpoint capabilities before heavy usage\nlet chain_id = provider.request(\"eth_chainId\", ()).await?; // basic liveness probe\nanyhow::ensure!(endpoint_supports_archive(&endpoint) || block_is_recent(block), \"archive RPC required\");","typeGuard":"fn is_rate_limited(err: &anyhow::Error) -> bool {\n    err.to_string().contains(\"RPC error -32005\")\n}","tryCatchPattern":"let out = loop {\n    match rpc.call_at(from, to, value, data, block).await {\n        Ok(out) => break Ok(out),\n        Err(e) if is_rate_limited(&e) && attempts < MAX => { attempts += 1; sleep(backoff(attempts)).await; }\n        Err(e) => break Err(e),\n    }\n};","preventionTips":["Use a paid/archive provider for historical calls instead of free public endpoints","Implement exponential backoff with jitter on rate-limit codes","Health-probe the endpoint (eth_chainId, eth_blockNumber) before workloads","Keep a fallback endpoint list and rotate on persistent RPC errors"],"tags":["evm","rpc","json-rpc","network"],"backgroundTag":"api-error-response","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}