nautechsystems/nautilus_trader · error

RPC provider error {code}: {message}

Error message

RPC provider error {code}: {message}

What it means

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.

Source

Thrown at crates/adapters/blockchain/src/rpc/http.rs:173

        timeout_secs: Option<u64>,
    ) -> anyhow::Result<T> {
        let bytes = self
            .send_rpc_request(rpc_request, timeout_secs)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to execute eth call RPC request: {e}"))?;
        let parsed =
            serde_json::from_slice::<RpcNodeHttpResponse<T>>(bytes.as_ref()).map_err(|e| {
                let raw_response = String::from_utf8_lossy(bytes.as_ref());
                let preview = rpc_response_preview(&raw_response);
                anyhow::anyhow!("Failed to parse eth call response: {e}\nRaw response: {preview}")
            })?;

        // Check for non-standard rate limit error (e.g., Infura)
        // These responses have code/message at top level without jsonrpc field
        if parsed.jsonrpc.is_none()
            && let (Some(code), Some(message)) = (parsed.code, parsed.message)
        {
            anyhow::bail!("RPC provider error {code}: {message}");
        }

        if let Some(error) = parsed.error {
            anyhow::bail!("RPC error {}: {}", error.code, error.message);
        }

        parsed
            .result
            .ok_or_else(|| anyhow::anyhow!("Response missing both result and error fields"))
    }

    /// Creates a properly formatted `eth_call` JSON-RPC request object targeting a specific contract address with encoded function data.
    #[must_use]
    pub fn construct_eth_call(
        &self,
        to: &str,
        call_data: &[u8],
        block: Option<u64>,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the `code` in the message: 429/-32005-style codes mean rate limiting — back off and retry with exponential delay and jitter
  2. Verify the RPC URL and API key are correct and the project is active in the provider dashboard
  3. Distribute requests across multiple RPC endpoints or upgrade the provider plan to raise the rate limit
  4. Add a transport layer that classifies this error shape (top-level code/message, no jsonrpc) and applies provider-specific retry policy

Example fix

// before: single endpoint, hammering rate limit
let bal = rpc.get_balance_with_timeout(addr, None, timeout).await?;
// after: handle provider errors with backoff/multi-endpoint
match rpc.get_balance_with_timeout(addr, None, timeout).await {
    Err(e) if e.to_string().contains("RPC provider error 429") => {
        tokio::time::sleep(backoff.next()).await;
        rpc_backup.get_balance_with_timeout(addr, None, timeout).await
    }
    other => other,
}
Defensive patterns

Strategy: retry

Validate before calling

// No pre-call validation possible (provider-side condition). Prefer proactive throttling:
// keep request rate under provider limit, e.g. a token-bucket limiter around every call.

Try / catch

match rpc_call().await {
    Err(e) if e.to_string().contains("RPC provider error") => {
        // parse code; retry with exponential backoff + jitter, then fail over to backup endpoint
    }
    other => other,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/88fdfc1a4438dd2e. Report an issue: GitHub.