{"record":{"id":"88fdfc1a4438dd2e","repo":"nautechsystems/nautilus_trader","slug":"rpc-provider-error-code-message","errorCode":null,"errorMessage":"RPC provider error {code}: {message}","messagePattern":"RPC provider error (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/http.rs","lineNumber":173,"sourceCode":"        timeout_secs: Option<u64>,\n    ) -> anyhow::Result<T> {\n        let bytes = self\n            .send_rpc_request(rpc_request, timeout_secs)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to execute eth call RPC request: {e}\"))?;\n        let parsed =\n            serde_json::from_slice::<RpcNodeHttpResponse<T>>(bytes.as_ref()).map_err(|e| {\n                let raw_response = String::from_utf8_lossy(bytes.as_ref());\n                let preview = rpc_response_preview(&raw_response);\n                anyhow::anyhow!(\"Failed to parse eth call response: {e}\\nRaw response: {preview}\")\n            })?;\n\n        // Check for non-standard rate limit error (e.g., Infura)\n        // These responses have code/message at top level without jsonrpc field\n        if parsed.jsonrpc.is_none()\n            && let (Some(code), Some(message)) = (parsed.code, parsed.message)\n        {\n            anyhow::bail!(\"RPC provider error {code}: {message}\");\n        }\n\n        if let Some(error) = parsed.error {\n            anyhow::bail!(\"RPC error {}: {}\", error.code, error.message);\n        }\n\n        parsed\n            .result\n            .ok_or_else(|| anyhow::anyhow!(\"Response missing both result and error fields\"))\n    }\n\n    /// Creates a properly formatted `eth_call` JSON-RPC request object targeting a specific contract address with encoded function data.\n    #[must_use]\n    pub fn construct_eth_call(\n        &self,\n        to: &str,\n        call_data: &[u8],\n        block: Option<u64>,","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/http.rs#L155-L191","documentation":"The RPC provider returned a non-standard error payload with `code` and `message` at the top level of the JSON response and no `jsonrpc` field. Providers like Infura return this shape for rate limiting or account/plan issues instead of a standard JSON-RPC error object. The library surfaces the provider's code and message verbatim so the caller can distinguish provider-side problems from JSON-RPC protocol errors.","triggerScenarios":"An HTTP call via `execute_rpc_call` (or `get_balance_with_timeout`) receives a 200/4xx body that parses but has `jsonrpc: null` plus top-level `code` and `message` fields — e.g. Infura's `{\"code\":429,\"message\":\"rate limit exceeded\"}` or project-tier/quota errors.","commonSituations":"Exceeding Infura/Alchemy free-tier rate limits under load; expired or invalid API keys causing provider-level error responses; sending requests to the wrong provider endpoint so a non-JSON-RPC gateway answers; shared endpoints throttling during network congestion.","solutions":["Read the `code` in the message: 429/-32005-style codes mean rate limiting — back off and retry with exponential delay and jitter","Verify the RPC URL and API key are correct and the project is active in the provider dashboard","Distribute requests across multiple RPC endpoints or upgrade the provider plan to raise the rate limit","Add a transport layer that classifies this error shape (top-level code/message, no jsonrpc) and applies provider-specific retry policy"],"exampleFix":"// before: single endpoint, hammering rate limit\nlet bal = rpc.get_balance_with_timeout(addr, None, timeout).await?;\n// after: handle provider errors with backoff/multi-endpoint\nmatch rpc.get_balance_with_timeout(addr, None, timeout).await {\n    Err(e) if e.to_string().contains(\"RPC provider error 429\") => {\n        tokio::time::sleep(backoff.next()).await;\n        rpc_backup.get_balance_with_timeout(addr, None, timeout).await\n    }\n    other => other,\n}","handlingStrategy":"retry","validationCode":"// No pre-call validation possible (provider-side condition). Prefer proactive throttling:\n// keep request rate under provider limit, e.g. a token-bucket limiter around every call.","typeGuard":null,"tryCatchPattern":"match rpc_call().await {\n    Err(e) if e.to_string().contains(\"RPC provider error\") => {\n        // parse code; retry with exponential backoff + jitter, then fail over to backup endpoint\n    }\n    other => other,\n}","preventionTips":["Stay under provider rate limits (use a rate limiter / batching)","Rotate multiple RPC endpoints and fail over on provider errors","Monitor provider dashboard quotas and keep API keys valid"],"tags":["rpc","rate-limit","infura","json-rpc","provider-error"],"backgroundTag":"rate-limit-exceeded","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"}