nautechsystems/nautilus_trader · error
Response missing both result and error fields
Error message
Response missing both result and error fields
What it means
execute_rpc_call_with_timeout expects every JSON-RPC response to carry either a result or an error field. If RpcNodeHttpResponse has neither, the node returned a structurally valid but semantically empty response, and the code fails with this error rather than returning None. This indicates a non-conforming or buggy RPC endpoint.
Source
Thrown at crates/adapters/blockchain/src/rpc/http.rs:182
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"))
}
/// Creates a properly formatted `eth_call` JSON-RPC request object targeting a specific contract address with encoded function data.
#[must_use]
pub fn construct_eth_call(
&self,
to: &str,
call_data: &[u8],
block: Option<u64>,
) -> serde_json::Value {
self.construct_eth_call_request(None, to, call_data, block)
}
fn construct_eth_call_request(
&self,
from: Option<&Address>,
to: &str,
call_data: &[u8],View on GitHub (pinned to 18893faf8b)
Solutions
- Log the raw response body for this case to see what the node actually returned.
- Point the client directly at a standard JSON-RPC node, bypassing any gateway/proxy layer.
- If the provider legitimately returns this shape, pre-validate with a simple request (eth_chainId) and switch providers if non-conformant.
- Update to a newer version of the client, which may handle additional non-standard response shapes.
Defensive patterns
Strategy: try-catch
Validate before calling
// health-check the provider conforms to JSON-RPC at startup
let v: serde_json::Value = post_json(rpc_url, eth_chain_id_request()).await?;
if v.get("result").is_none() && v.get("error").is_none() {
return Err("provider returns non-conformant JSON-RPC responses".into());
} Try / catch
match execute_rpc_call(&client, req).await {
Ok(v) => Ok(v),
Err(e) if e.to_string().contains("Response missing both result and error fields") => {
// non-conformant endpoint: log raw body and failover
tracing::error!("non-conformant RPC response; switching provider");
switch_to_backup_provider().await
}
Err(e) => Err(e),
} Prevention
- Run a JSON-RPC conformance probe (eth_chainId) when adding a new provider.
- Bypass API gateways/proxies that rewrite JSON-RPC envelopes.
- Keep the client updated to handle known non-standard provider shapes.
- Failover automatically when a provider repeatedly returns empty envelopes.
When it happens
Trigger: Calling execute_rpc_call or get_balance_with_timeout against a node that returns a JSON object without both 'result' and 'error' — e.g. a partially standard-compliant proxy, a load balancer health response, or a non-standard rate-limit body that also lacked top-level code/message.
Common situations: Routing through API gateways that intercept and return custom JSON envelopes; misconfigured reverse proxies in front of the node; provider returning unusual shaped errors that evade both the error branch and the Infura-style rate-limit check.
Related errors
- RPC provider error {code}: {message}
- RPC error {}: {}
- {method} RPC error {}
- eth_call RPC error {code}
- eth_call RPC error {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/aa131d40b65490f6.
Report an issue: GitHub.