nautechsystems/nautilus_trader · error
eth_call RPC error {}
Error message
eth_call RPC error {} What it means
Raised by `call_result_at` when the RPC response contains a structured `error` object whose code/message is not recognized as a revert. Like error 561 but for the standard `error` field of the JSON-RPC response; the error code is embedded in the message to help identify the node-side failure.
Source
Thrown at crates/adapters/blockchain/src/rpc/http.rs:560
_ => 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`.
///
/// # 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,View on GitHub (pinned to 18893faf8b)
Solutions
- Check the embedded error code: -32000 'header not found' → use an archive node or a lower block.
- Raise the gas limit/price if the error mentions gas.
- Validate parameters passed into the call (address checksums, block encoding) for -32602.
- Retry against a different RPC endpoint for -32603 internal errors.
Defensive patterns
Strategy: retry
Validate before calling
// Ensure the block is within node retention
let latest: u64 = provider.request("eth_blockNumber", ()).await?;
anyhow::ensure!(block <= latest.saturating_sub(REORG_MARGIN), "block too old for non-archive node"); Type guard
fn is_gas_error(err: &anyhow::Error) -> bool {
let s = err.to_string();
s.contains("gas required exceeds allowance") || s.contains("out of gas")
} Try / catch
match rpc.call_at(from, to, value, data, block).await {
Err(e) if is_gas_error(&e) => retry_with_higher_gas(),
Err(e) if e.to_string().contains("header not found") => switch_to_archive_endpoint(),
other => other,
} Prevention
- Match node type to query age: archive nodes for old blocks
- Set realistic gas caps for complex contract calls
- Log the embedded JSON-RPC code from the error message to triage quickly
- Retry -32603 internal errors against a second endpoint
When it happens
Trigger: `eth_call` rejected with a structured non-revert error: -32000 execution errors not containing 'revert' (e.g. 'gas required exceeds allowance', 'header not found'), -32603 internal error, -32602 invalid params.
Common situations: Querying a block beyond the node's retention ('header not found' on non-archive nodes); gas limit exceeded for complex calls; malformed request params; provider internal errors during high load.
Related errors
- eth_call RPC error {code}
- Finalized block {} does not contain transaction {}
- RPC provider error {code}: {message}
- RPC error {}: {}
- {method} RPC error {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ce66605f3eb2b1c5.
Report an issue: GitHub.