{"record":{"id":"4168e6e16238d196","repo":"nautechsystems/nautilus_trader","slug":"eth-getblockbynumber-returned-block-for-request","errorCode":null,"errorMessage":"eth_getBlockByNumber returned block {} for requested block {number}","messagePattern":"eth_getBlockByNumber returned block (.+?) for requested block (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/http.rs","lineNumber":675,"sourceCode":"                \"Failed to read the consensus finalized block; the execution endpoint must support the finalized tag: {e}\"\n            )\n        })\n    }\n\n    /// Returns a numbered canonical block, optionally with full transactions.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the RPC call fails or the result is missing or malformed.\n    pub async fn block_by_number(\n        &self,\n        number: u64,\n        full_transactions: bool,\n    ) -> anyhow::Result<RpcBlock> {\n        let block = self\n            .block_by_tag(&format!(\"0x{number:x}\"), full_transactions)\n            .await?;\n        anyhow::ensure!(\n            block.number == number,\n            \"eth_getBlockByNumber returned block {} for requested block {number}\",\n            block.number\n        );\n        Ok(block)\n    }\n\n    async fn block_by_tag(&self, tag: &str, full_transactions: bool) -> anyhow::Result<RpcBlock> {\n        let result: Option<RpcBlockResponse> = self\n            .execute_execution_rpc_call(\n                \"eth_getBlockByNumber\",\n                serde_json::json!([tag, full_transactions]),\n            )\n            .await?;\n        let response = result.ok_or_else(|| {\n            anyhow::anyhow!(\"eth_getBlockByNumber returned no result for block tag {tag}\")\n        })?;\n        let mut block = response.block;","sourceCodeStart":657,"sourceCodeEnd":693,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/http.rs#L657-L693","documentation":"`block_by_number` requests a block by hex height via `block_by_tag(\"0x{number:x}\")` and then asserts that the block the node returned is actually the requested height. If the node returns a block whose `number` differs (or a recent/pending resolution shifted the tag), the mismatch is reported with both numbers.","triggerScenarios":"The node resolves the `0x<hex>` tag to a different block than requested — typically a race on a `latest`-style fallback, a node that rounds unsupported heights to latest, or a proxy/node bug returning a neighboring block. Also possible if the node returns block `number` as null for a pruned/unavailable height.","commonSituations":"Querying a height beyond the node's synced head (node returns latest instead); pruned nodes serving reorg-affected heights; caching proxies serving a stale block for the requested tag.","solutions":["Verify the node is fully synced (`eth_syncing`) and the requested height is below the chain head","Retry the request; a transient race (e.g. reorg during resolution) usually resolves","Bypass caching proxies or disable response caching for eth_getBlockByNumber","Use a different node/archive provider if heights are pruned or consistently mismatched"],"exampleFix":"// before: querying height beyond node head\nlet block = client.block_by_number(9_999_999_999, false).await?; // node returns its head -> mismatch\n// after: clamp to node head first\nlet head = client.latest_block().await?;\nlet target = number.min(head.number);\nlet block = client.block_by_number(target, false).await?;","handlingStrategy":"retry","validationCode":"async fn height_in_range(url: &str, number: u64) -> bool {\n    let head: u64 = fetch_chain_head(url).await.unwrap_or(0);\n    number <= head\n}","typeGuard":null,"tryCatchPattern":"match client.block_by_number(number, false).await {\n    Ok(b) => Ok(b),\n    Err(e) if e.to_string().contains(\"for requested block\") => {\n        // transient race or unsynced node: retry, then fail over\n        tokio::time::sleep(Duration::from_millis(200)).await;\n        client.block_by_number(number, false).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Confirm the node is fully synced before querying specific heights","Request heights at or below the node's head (`eth_blockNumber`)","Avoid caching layers in front of eth_getBlockByNumber or key caches on exact heights","Use archive providers for historical heights that pruned nodes cannot serve correctly"],"tags":["rpc","ethereum","blocks","consistency"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}