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
- Retry the call; transient node bugs often resolve on a second attempt or a different node
- Check node logs for internal errors around the failed eth_call
- Point the RPC client at a different execution client / provider
- 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
- Retry once or twice with backoff — null results are often transient node bugs
- Diversify across multiple execution providers and fail over on null results
- Keep node software current; older clients have known null-result bugs
- Route eth_call traffic away from caching proxies that mangle JSON-RPC responses
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
- eth_call execution reverted
- Failed to execute eth call RPC request: {e}
- eth_call redirect rejected
- eth_call request failed
- Failed to parse eth_call response
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/dcd4cf223c6142de.
Report an issue: GitHub.