nautechsystems/nautilus_trader · error
Failed to parse eth call response: {e} Raw response: {previe
Error message
Failed to parse eth call response: {e}
Raw response: {preview} What it means
After a successful transport, execute_rpc_call_with_timeout deserializes the bytes into RpcNodeHttpResponse<T>. If the body is not a well-formed JSON-RPC response object, it fails with this error and includes a truncated raw response preview for debugging. This means the node returned HTTP 200 but with unexpected content.
Source
Thrown at crates/adapters/blockchain/src/rpc/http.rs:165
/// the response into the specified type T.
///
/// # Errors
///
/// Returns an error if the HTTP RPC request fails or the response cannot be parsed.
pub async fn execute_rpc_call_with_timeout<T: DeserializeOwned>(
&self,
rpc_request: serde_json::Value,
timeout_secs: Option<u64>,
) -> anyhow::Result<T> {
let bytes = self
.send_rpc_request(rpc_request, timeout_secs)
.await
.map_err(|e| anyhow::anyhow!("Failed to execute eth call RPC request: {e}"))?;
let parsed =
serde_json::from_slice::<RpcNodeHttpResponse<T>>(bytes.as_ref()).map_err(|e| {
let raw_response = String::from_utf8_lossy(bytes.as_ref());
let preview = rpc_response_preview(&raw_response);
anyhow::anyhow!("Failed to parse eth call response: {e}\nRaw response: {preview}")
})?;
// Check for non-standard rate limit error (e.g., Infura)
// These responses have code/message at top level without jsonrpc field
if parsed.jsonrpc.is_none()
&& let (Some(code), Some(message)) = (parsed.code, parsed.message)
{
anyhow::bail!("RPC provider error {code}: {message}");
}
if let Some(error) = parsed.error {
anyhow::bail!("RPC error {}: {}", error.code, error.message);
}
parsed
.result
.ok_or_else(|| anyhow::anyhow!("Response missing both result and error fields"))
}View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the 'Raw response' preview in the error message — it reveals whether the body is HTML, empty, or truncated JSON.
- Confirm the configured URL is the JSON-RPC endpoint of the node (not a dashboard or REST API path).
- Check provider rate limits / plan quotas if the preview shows a rate-limit or upgrade notice.
- Ensure no proxy or middleware is rewriting the response; test the same eth_call with curl.
Defensive patterns
Strategy: try-catch
Validate before calling
// probe that the URL returns JSON-RPC shaped content before using it
let body: serde_json::Value = probe_post(rpc_url, eth_chain_id_request()).await?;
if body.get("jsonrpc").is_none() && body.get("result").is_none() && body.get("error").is_none() {
return Err("endpoint does not speak JSON-RPC".into());
} Try / catch
match execute_rpc_call(&client, req).await {
Ok(v) => Ok(v),
Err(e) if e.to_string().contains("Failed to parse eth call response") => {
// extract the raw preview, inspect for HTML/rate-limit text, then failover
switch_to_backup_provider().await
}
Err(e) => Err(e),
} Prevention
- Always read the 'Raw response' preview in the error before guessing the cause.
- Point the client at the JSON-RPC endpoint, not a dashboard/REST path.
- Watch for HTML in responses — a sign of rate limiting or proxy interception.
- Test the endpoint with curl using the same eth_call payload.
When it happens
Trigger: Calling execute_rpc_call or get_balance_with_timeout when the RPC endpoint returns a non-JSON or malformed body — provider error pages, HTML rate-limit notices, empty bodies, or proxies intercepting the request.
Common situations: Rate limiting from providers like Infura/Alchemy returning HTML or plain-text errors with 200; corporate proxies or captive portals injecting content; pointing the client at a non-JSON-RPC URL (e.g. a REST endpoint or web page).
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
- Expected 2 token IDs, received {}
- Expected 2 outcomes, received {}
- Failed to execute eth call RPC request: {e}
- Response missing both result and error fields
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/80416d921d5f1d3e.
Report an issue: GitHub.