nautechsystems/nautilus_trader · error

eth_call request failed

Error message

eth_call request failed

What it means

Catch-all error for `eth_call` requests: any transport error from `send_rpc_request` that is not a rejected redirect (connection failure, timeout, TLS, HTTP errors) is surfaced as "eth_call request failed". The specific cause is not included in the message.

Source

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

        if let Some(from) = from {
            call["from"] = serde_json::json!(from);
        }
        let request = serde_json::json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "eth_call",
            "params": [call, block_parameter(Some(block))],
        });
        let bytes = self
            .send_rpc_request(request, Some(EXECUTION_RPC_TIMEOUT_SECS))
            .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);

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check node health with a lightweight call (eth_chainId) to distinguish transport vs method issues
  2. Increase the execution RPC timeout or reduce gas/complexity of the call
  3. Inspect underlying client logs for the concrete transport error
  4. Add retry with backoff for transient network failures

Example fix

// before: single attempt, opaque failure
let out = client.call_at(&tx, Some(block)).await?;
// after: retry transient failures with backoff
let out = match client.call_at(&tx, Some(block)).await {
    Ok(v) => v,
    Err(e) if is_transient(&e) => {
        tokio::time::sleep(Duration::from_millis(250)).await;
        client.call_at(&tx, Some(block)).await?
    }
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: node reachable and responsive
// curl -sf -X POST $URL -H 'Content-Type: application/json' \
//   -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'

Try / catch

match client.call_at(&tx, block).await {
    Err(e) if e.to_string() == "eth_call request failed" => {
        // inspect transport cause via logs; retry transient failures with backoff
    }
    other => other,
}

Prevention

When it happens

Trigger: `call_at` failing due to node unreachability, EXECUTION_RPC_TIMEOUT_SECS elapsing, connection reset, DNS failure, or non-redirect HTTP error statuses from the endpoint.

Common situations: eth_call timeouts on heavy contract simulations, node rate limiting or blocking, provider outage, or network partitions between client and node.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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