{"record":{"id":"6b06d9951142dfb8","repo":"nautechsystems/nautilus_trader","slug":"verified-inclusion-header-does-not-match-the-final","errorCode":null,"errorMessage":"Verified inclusion header does not match the finalized receipt","messagePattern":"Verified inclusion header does not match the finalized receipt","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":4681,"sourceCode":"    let rejected = OrderRejected::new(\n        emitter.trader_id(),\n        order.strategy_id(),\n        order.instrument_id(),\n        order.client_order_id(),\n        emitter.account_id(),\n        format!(\"Transaction {} reverted on-chain\", included.tx_hash).into(),\n        execution_event_id(included.tx_hash, b\"reverted\"),\n        ts_event,\n        ts_event,\n        false,\n        false,\n    );\n    emitter.try_send_order_event(OrderEventAny::Rejected(rejected))\n}\n\nfn finalized_inclusion_time(included: &IncludedTransaction) -> anyhow::Result<UnixNanos> {\n    let inclusion = &included.finality.inclusion_header;\n    anyhow::ensure!(\n        inclusion.number == included.block_number\n            && inclusion.hash == included.receipt.block_hash.to_string(),\n        \"Verified inclusion header does not match the finalized receipt\"\n    );\n    let timestamp = inclusion.timestamp;\n    let nanos = timestamp\n        .checked_mul(NANOSECONDS_IN_SECOND)\n        .ok_or_else(|| anyhow::anyhow!(\"Verified inclusion timestamp exceeds nanoseconds\"))?;\n    Ok(UnixNanos::from(nanos))\n}\n\nfn execution_event_id(tx_hash: B256, event: &[u8]) -> UUID4 {\n    let mut identity = Vec::with_capacity(tx_hash.len() + event.len());\n    identity.extend_from_slice(tx_hash.as_slice());\n    identity.extend_from_slice(event);\n    let digest = keccak256(identity);\n    let mut bytes = [0u8; 16];\n    bytes.copy_from_slice(&digest[..16]);","sourceCodeStart":4663,"sourceCodeEnd":4699,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L4663-L4699","documentation":"To timestamp a finalized order event, the adapter cross-checks the verified inclusion block header against the finalized receipt: the header's block number must equal `included.block_number` and its hash must equal `receipt.block_hash`. This ensure! fires when they disagree — the header the finality layer attests to is not the block the receipt was mined in. It is an internal consistency guard against reorgs, mis-attributed receipts, or corrupted finality data.","triggerScenarios":"`finalized_inclusion_time` is called on an IncludedTransaction where `finality.inclusion_header.number != block_number` or `inclusion_header.hash != receipt.block_hash` — e.g. after a reorg the receipt points at a block different from the finality-verified header, or finality data was populated from a mismatched source.","commonSituations":"A chain reorg moved the transaction to a different block after finality data was captured, finality headers cached from an earlier verification run, mismatched block-hash string formatting (e.g. checksummed vs hex) between sources, or a provider returning headers/receipts from different forks.","solutions":["Re-fetch the receipt and canonical block header at `included.block_number` and rebuild the IncludedTransaction after the mismatch","Check for a reorg: compare the header hash against the current canonical chain at that height","Ensure both header and receipt come from the same provider/fork within the same session","If hashes are string-compared, normalize formatting (lowercase hex) on both sides"],"exampleFix":"// before\nlet hash_a = inclusion.hash;\nlet hash_b = included.receipt.block_hash.to_string();\n// after\nlet hash_a = inclusion.hash.to_lowercase();\nlet hash_b = included.receipt.block_hash.to_string().to_lowercase();","handlingStrategy":"type-guard","validationCode":"fn inclusion_consistent(included: &IncludedTransaction) -> bool {\n    let h = &included.finality.inclusion_header;\n    h.number == included.block_number\n        && h.hash.eq_ignore_ascii_case(&included.receipt.block_hash.to_string())\n}","typeGuard":"fn has_matching_inclusion_header(included: &IncludedTransaction) -> bool {\n    let h = &included.finality.inclusion_header;\n    h.number == included.block_number && h.hash.eq_ignore_ascii_case(&included.receipt.block_hash.to_string())\n}","tryCatchPattern":"match finalized_inclusion_time(included) {\n    Ok(ts) => emit_rejected(included, ts),\n    Err(e) if e.to_string().contains(\"does not match the finalized receipt\") => {\n        tracing::error!(\"header/receipt mismatch for {} — possible reorg; refetching\", included.tx_hash);\n        // rebuild IncludedTransaction from canonical chain before proceeding\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Rebuild IncludedTransaction from fresh canonical data after any detected reorg","Never cache finality headers across sessions or fork transitions","Normalize block hash casing (lowercase hex) wherever hashes are compared as strings","Use a single provider session for header and receipt reads so they can't come from different forks"],"tags":["blockchain","finality","reorg","consistency-check"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}