nautechsystems/nautilus_trader · error
RPC error {}: {}
Error message
RPC error {}: {} What it means
The RPC node returned a standard JSON-RPC error object (`{"error":{"code":..,"message":..}}`) for the request. The code is the JSON-RPC error code (e.g. -32601 method not found, -32000 server error, -32005 limit exceeded) and the message is the node's own description. This indicates the request reached the node but was rejected at the protocol/execution level.
Source
Thrown at crates/adapters/blockchain/src/rpc/http.rs:177
.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"))
}
/// 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)
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Parse the numeric code: -32601 means unsupported method (check endpoint capabilities); -32602 means invalid params (fix arguments); execution errors mean fix the call itself
- Validate address/ABI parameters (checksummed 0x-hex, valid block tags) before sending
- Retry only for transient codes (e.g. -32005 limit exceeded) with backoff; fail fast on -32601/-32602
- Try a different RPC endpoint/node if the error is node-specific
Example fix
// before
let balance = rpc.get_balance_with_timeout(addr, None, timeout).await?;
// after: validate params first
let addr = address.to_checksum(None); // ensure valid 0x hex
if !addr.starts_with("0x") || addr.len() != 42 { anyhow::bail!("invalid address"); }
let balance = rpc.get_balance_with_timeout(addr, None, timeout).await?; Defensive patterns
Strategy: try-catch
Validate before calling
fn is_valid_address(a: &str) -> bool { a.starts_with("0x") && a.len() == 42 && a[2..].chars().all(|c| c.is_ascii_hexdigit()) } Try / catch
match rpc_call().await {
Err(e) if e.to_string().contains("RPC error -32005") => retry_with_backoff(),
Err(e) if e.to_string().contains("RPC error -32601") => switch_endpoint(),
Err(e) => return Err(e),
Ok(v) => Ok(v),
} Prevention
- Validate all params (addresses, block tags, hex encoding) before sending
- Retry only transient codes (-32005, timeout-like); fail fast on -32601/-32602
- Check endpoint capability docs for archive/unsupported methods
When it happens
Trigger: Any `execute_rpc_call` / `get_balance_with_timeout` call where the node responds with a populated `error` field: unsupported method, invalid params, execution reverted, or node-side limit exceeded.
Common situations: Calling methods the node doesn't support (e.g. archive methods on a full node); malformed hex addresses or block tags in params; `eth_call` reverting due to contract logic; provider rejecting requests from unauthenticated or rate-limited projects.
Related errors
- {method} RPC error {}
- Included wrap transaction {tx_hash} has invalid block number
- RPC provider error {code}: {message}
- {method} RPC error {code}
- eth_call RPC error {code}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e1bf0ae6084ed814.
Report an issue: GitHub.