nautechsystems/nautilus_trader · error

eth_call RPC error {code}

Error message

eth_call RPC error {code}

What it means

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.

Source

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

            .await
            .map_err(|e| match e {
                BlockchainRpcClientError::ClientError(message)
                    if message.contains("redirect response rejected") =>
                {
                    anyhow::anyhow!("eth_call redirect rejected")
                }
                _ => anyhow::anyhow!("eth_call request failed"),
            })?;
        let parsed = serde_json::from_slice::<RpcNodeHttpResponse<String>>(bytes.as_ref())
            .map_err(|_| anyhow::anyhow!("Failed to parse eth_call response"))?;

        if parsed.jsonrpc.is_none()
            && let (Some(code), Some(message)) = (parsed.code, parsed.message)
        {
            if eth_call_error_is_revert(code, &message) {
                return Ok(RpcCallResult::Reverted);
            }
            anyhow::bail!("eth_call RPC error {code}");
        }

        if let Some(error) = parsed.error {
            if eth_call_error_is_revert(error.code, &error.message) {
                return Ok(RpcCallResult::Reverted);
            }
            anyhow::bail!("eth_call RPC error {}", error.code);
        }
        let value = parsed
            .result
            .ok_or_else(|| anyhow::anyhow!("eth_call returned no result"))?;
        let stripped = value.strip_prefix("0x").unwrap_or(&value);
        let bytes = hex::decode(stripped)
            .map_err(|_| anyhow::anyhow!("Failed to decode eth_call response"))?;
        Ok(RpcCallResult::Success(Bytes::from(bytes)))
    }

    /// Estimates the gas required for a transaction via `eth_estimateGas`.

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the reported JSON-RPC `code` and map it: -32005 rate limit → back off/retry; -32601 → check node capabilities.
  2. Use an archive node if calling at historical blocks; execution reverted-at-genesis style errors on non-archive nodes look like this.
  3. Add retry with backoff for transient codes (rate limit, timeout).
  4. Verify the endpoint URL and that the provider supports `eth_call` with the block parameter used.

Example fix

// before
let out = rpc.call_at(from, to, value, data, block).await?;
// after
let out = match rpc.call_at(from, to, value, data, block).await {
    Ok(out) => out,
    Err(e) if e.to_string().contains("RPC error -32005") => {
        tokio::time::sleep(BACKOFF).await;
        rpc.call_at(from, to, value, data, block).await?
    }
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: retry

Validate before calling

// Check endpoint capabilities before heavy usage
let chain_id = provider.request("eth_chainId", ()).await?; // basic liveness probe
anyhow::ensure!(endpoint_supports_archive(&endpoint) || block_is_recent(block), "archive RPC required");

Type guard

fn is_rate_limited(err: &anyhow::Error) -> bool {
    err.to_string().contains("RPC error -32005")
}

Try / catch

let out = loop {
    match rpc.call_at(from, to, value, data, block).await {
        Ok(out) => break Ok(out),
        Err(e) if is_rate_limited(&e) && attempts < MAX => { attempts += 1; sleep(backoff(attempts)).await; }
        Err(e) => break Err(e),
    }
};

Prevention

When it happens

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

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

Related errors


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