nautechsystems/nautilus_trader · error

eth_call returned no result

Error message

eth_call returned no result

What it means

Raised in `call_result_at` when the parsed `eth_call` JSON-RPC response contains neither a `result` field nor an error code/message pair, so there is no value to decode. The library treats a missing `result` as fatal because `eth_call` must return either data or an error per the JSON-RPC spec.

Source

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

        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`.
    ///
    /// # Errors
    ///
    /// Returns an error if the RPC call fails (including node-side revert of the simulated
    /// transaction) or the result is missing or malformed.
    pub async fn estimate_gas(
        &self,
        from: &Address,
        to: &Address,
        value: U256,
        data: &[u8],

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Retry the call; transient node bugs often resolve on a second attempt or a different node
  2. Check node logs for internal errors around the failed eth_call
  3. Point the RPC client at a different execution client / provider
  4. If a proxy sits between client and node, bypass it or fix its JSON handling

Example fix

// before: node returns {"jsonrpc":"2.0","id":1} with no result
// after: add fallback to a second provider
match primary.call_at(tx, block).await {
    Ok(res) => Ok(res),
    Err(e) if e.to_string().contains("returned no result") => fallback.call_at(tx, block).await,
    Err(e) => Err(e),
}
Defensive patterns

Strategy: retry

Try / catch

match client.call_at(&tx, block).await {
    Ok(res) => Ok(res),
    Err(e) if e.to_string().contains("eth_call returned no result") => {
        tokio::time::sleep(Duration::from_millis(250)).await;
        client.call_at(&tx, block).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: The node responds with a JSON-RPC envelope whose `result` field is absent or JSON `null` — e.g. some nodes omit `result` on internal errors, or a proxy strips the field; the response also lacks a recognizable `{code,message}` error object.

Common situations: Buggy or overloaded node returning `null` results; intermediary caching proxy dropping fields; mismatched node versions (e.g. pre-merge endpoints) that fail silently on certain eth_call payloads.

Related errors


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