nautechsystems/nautilus_trader · error
Fetched block {} while requesting RPC snapshot block {}
Error message
Fetched block {} while requesting RPC snapshot block {} What it means
block_scoped_snapshot_position_from_block checks that the Block object it received has the same number as the block_number that was requested when building an RPC snapshot. A mismatch means the caller fetched (or was handed) the wrong block for the requested snapshot position. The library bails to prevent constructing a BlockPosition from inconsistent data.
Source
Thrown at crates/adapters/blockchain/src/data/core.rs:2300
let block = blocks_stream
.next()
.await
.with_context(|| format!("failed to fetch block {block_number} for RPC snapshot"))?;
let block_position =
Self::block_scoped_snapshot_position_from_block(&mut self.cache, &block, block_number)?;
self.cache.add_pool_event_blocks_batch(vec![block]).await?;
Ok(block_position)
}
fn block_scoped_snapshot_position_from_block(
cache: &mut BlockchainCache,
block: &Block,
block_number: u64,
) -> anyhow::Result<BlockPosition> {
if block.number != block_number {
anyhow::bail!(
"Fetched block {} while requesting RPC snapshot block {}",
block.number,
block_number
);
}
cache.cache_block_metadata(block);
Ok(BlockPosition::new(
block.number,
block.hash.clone(),
BLOCK_SCOPED_SNAPSHOT_INDEX,
BLOCK_SCOPED_SNAPSHOT_INDEX,
)
.with_block_hash(Some(block.hash.clone())))
}
/// Replays historical events for a pool to hydrate its profiler state.View on GitHub (pinned to 18893faf8b)
Solutions
- Fetch the block and the snapshot in one atomic request at a pinned block number or hash
- Assert block equality immediately after fetching and retry with a fresh fetch on mismatch
- Use block hashes instead of numbers to be reorg-safe
- Avoid reusing cached Block objects across snapshot requests
- Serialize snapshot construction so no cache invalidation can swap the block mid-flight
Example fix
// before: reusing possibly stale block let block = cache.get_cached_block(); let position = block_scoped_snapshot_position_from_block(&mut cache, &block, requested_number)?; // after: refetch the exact block requested let block = client.fetch_block(requested_number).await?; let position = block_scoped_snapshot_position_from_block(&mut cache, &block, requested_number)?;
Defensive patterns
Strategy: validation
Validate before calling
if block.number != block_number {
return Err(anyhow!("block mismatch: got {}, wanted {}", block.number, block_number));
} Type guard
fn is_requested_block(block: &Block, n: u64) -> bool { block.number == n } Try / catch
match build_snapshot_position(&mut cache, &block, n) {
Ok(pos) => pos,
Err(e) if e.to_string().contains("Fetched block") => retry_with_fresh_fetch(n).await?,
Err(e) => return Err(e),
} Prevention
- Fetch block body and snapshot atomically at a pinned block
- Do not reuse cached Block objects across snapshot requests
- Prefer block hashes to be reorg-safe
When it happens
Trigger: Calling the snapshot-position code path when block.number != block_number — typically after a helper returns a 'latest' block that has advanced past the requested number, or a caller passes a cached block from an earlier fetch alongside a newer block number.
Common situations: Race with block production: the node advanced between requesting the block number and fetching its body; a stale cached Block object reused with a fresh block_number; a reorg replacing the block at that height; passing block.number from a log instead of the snapshot request block.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- RPC tick {tick_value} does not match positions: derived gros
- Profiler receipt position does not match its ingestion water
- Profiler receipt contains {} logs at global index {}; expect
- Finalized block {} does not contain transaction {}
- Finalized execution transaction {tx_hash} no longer has a re
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0ed601ac0fc3aff3.
Report an issue: GitHub.