nautechsystems/nautilus_trader · error
eth_getStorageAt returned no result
Error message
eth_getStorageAt returned no result
What it means
`get_storage_at` requires the `eth_getStorageAt` result to be present; the parsed `Option<String>` result being `None` (JSON-RPC success with null result) produces this error. The library treats a null storage slot response as a failure rather than returning a default.
Source
Thrown at crates/adapters/blockchain/src/rpc/http.rs:403
/// Returns an error if the RPC call fails or the result is missing or malformed.
#[cfg(feature = "hypersync")]
#[allow(
dead_code,
reason = "Used by the independent verification read inventory"
)]
pub(crate) async fn get_storage_at(
&self,
address: &Address,
slot: &B256,
block: u64,
) -> anyhow::Result<B256> {
let result: Option<String> = self
.execute_execution_rpc_call(
"eth_getStorageAt",
serde_json::json!([address, slot, block_parameter(Some(block))]),
)
.await?;
let value = result.ok_or_else(|| anyhow::anyhow!("eth_getStorageAt returned no result"))?;
B256::from_str(&value)
.map_err(|_| anyhow::anyhow!("Failed to parse eth_getStorageAt response"))
}
async fn get_code_with_block(
&self,
address: &Address,
block: Option<u64>,
) -> anyhow::Result<Bytes> {
let result: Option<String> = self
.execute_execution_rpc_call(
"eth_getCode",
serde_json::json!([address, block_parameter(block)]),
)
.await?;
let hex_string = result.ok_or_else(|| anyhow::anyhow!("eth_getCode returned no result"))?;
let stripped = hex_string.strip_prefix("0x").unwrap_or(&hex_string);
let bytes = hex::decode(stripped)View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the address is a contract at the queried block (eth_getCode != 0x)
- Query at a block height at or after contract deployment
- Treat empty slots as B256::ZERO if your node returns null for zero storage
- Try a different node implementation that returns 0x000...0 for empty slots
Example fix
// before: assuming slot always returns a value
let value = client.get_storage_at(&addr, slot, Some(block)).await?;
// after: check contract exists at that block first
if client.get_code_at(&addr, Some(block)).await?.as_ref().is_empty() {
return Ok(B256::ZERO); // no contract -> no storage
}
let value = client.get_storage_at(&addr, slot, Some(block)).await?; Defensive patterns
Strategy: fallback
Validate before calling
// ensure the address is a contract with code at the queried block
let code = client.get_code_at(&address, Some(block)).await?;
if code.as_ref().is_empty() { /* no storage to read */ } Try / catch
let slot_value = match client.get_storage_at(&addr, slot, Some(block)).await {
Ok(v) => v,
Err(_) if !has_code => B256::ZERO, // treat missing storage as zero
Err(e) => return Err(e),
}; Prevention
- Confirm contract deployment block before querying historical storage
- Only query storage on addresses with bytecode at the target block
- Use nodes that return 0x000...0 instead of null for empty slots
- Validate addresses/slots before querying
When it happens
Trigger: Calling `get_storage_at` for an address/slot where the node returns `result: null` — e.g. a nonexistent contract address, a block before the contract existed, or a non-compliant node omitting the result field.
Common situations: Querying storage at a block height before the contract was deployed, querying an EOA address, or a node that returns null instead of the zero value for empty slots.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- eth_getCode returned no result
- Finalized block {} does not contain transaction {}
- Finalized execution transaction {tx_hash} no longer has a re
- Canonical head changed during signer-nonce replacement scan
- Finalized block {} changed from {} to {} before intent valid
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/3528b5d69107e4d0.
Report an issue: GitHub.