nautechsystems/nautilus_trader · error
Failed to parse eth_call response
Error message
Failed to parse eth_call response
What it means
This error is raised in `call_result_at` when the HTTP body returned by the node for an `eth_call` cannot be deserialized into the expected `RpcNodeHttpResponse<String>` JSON-RPC envelope. The library expects either a JSON-RPC 2.0 response (with `jsonrpc`/`result`) or a non-standard `{code, message}` error object; anything else (HTML, empty body, truncated JSON, proxy error pages) triggers it. It wraps the raw transport layer so callers get a single anyhow error for the eth_call path.
Source
Thrown at crates/adapters/blockchain/src/rpc/http.rs:545
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);
}
let value = parsed
.resultView on GitHub (pinned to 18893faf8b)
Solutions
- Verify the execution RPC URL points at a JSON-RPC endpoint (curl -X POST with an eth_chainId request) and not a dashboard or proxy page
- Inspect the raw response body (curl the same eth_call) to see whether the node returns HTML or malformed JSON
- Retry against a healthy node or another provider; persistent failures indicate node/proxy issues
- Upgrade the adapter/node if the node uses a non-standard JSON-RPC response shape
Example fix
// before: endpoint returns HTML on error, causing parse failure
rpc_url = "https://my-lb.example.com/eth" // LB returns HTML 502
// after: point directly at a JSON-RPC endpoint and pre-check health
rpc_url = "https://node.example.com:8545"
// curl -X POST $rpc_url -d '{"jsonrpc":"2.0","method":"eth_chainId","id":1}' Defensive patterns
Strategy: try-catch
Validate before calling
async fn rpc_endpoint_ok(url: &str) -> bool {
let body = reqwest::Client::new().post(url)
.json(&serde_json::json!({"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}))
.send().await.ok()?.text().await.ok()?;
body.trim_start().starts_with('{') && serde_json::from_str::<serde_json::Value>(&body).is_ok()
} Type guard
fn is_json_rpc_envelope(v: &serde_json::Value) -> bool {
v.is_object() && (v.get("jsonrpc").is_some() || v.get("result").is_some() || v.get("error").is_some())
} Try / catch
match client.call_at(&tx, block).await {
Ok(res) => handle(res),
Err(e) if e.to_string().contains("Failed to parse eth_call response") => {
log::warn!("non-JSON RPC body; failing over");
fallback_client.call_at(&tx, block).await
}
Err(e) => Err(e),
} Prevention
- Point the RPC URL directly at a JSON-RPC endpoint, never at a web UI or HTML-serving proxy
- Health-check the endpoint with an eth_chainId POST before starting workloads
- Disable intermediaries that replace JSON error bodies with HTML (Cloudflare challenge pages, LB error pages)
- Pin and monitor node/provider versions to avoid non-standard response shapes
When it happens
Trigger: The `eth_call` HTTP response body is not valid JSON, or is valid JSON that does not match the `RpcNodeHttpResponse<String>` shape (missing both `jsonrpc` and `result`/`code`/`message` fields), e.g. an HTML error page from a reverse proxy, a rate-limit text body, or a non-standard node response.
Common situations: Pointing the execution RPC URL at a load balancer or Cloudflare endpoint that returns HTML 502/429 pages; node returning chunked/truncated responses under load; misconfigured port hitting a web UI instead of the JSON-RPC endpoint.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse eth call response: {e} Raw response: {previe
- eth_call execution reverted
- Expected 2 token IDs, received {}
- Expected 2 outcomes, received {}
- Failed to execute eth call RPC request: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/19410fecc572ed18.
Report an issue: GitHub.