{"record":{"id":"f1b0cc4dd41f90b2","repo":"nautechsystems/nautilus_trader","slug":"verified-finalized-header-conflicts-with-its-ances","errorCode":null,"errorMessage":"Verified finalized header conflicts with its ancestry window","messagePattern":"Verified finalized header conflicts with its ancestry window","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":6041,"sourceCode":"            let start = ancestry_cursor.number.saturating_add(1);\n            let headers_verification = required_verification(\n                self.verification\n                    .verify_header_window(ancestry_cursor, end)\n                    .await,\n                \"Blockchain finalized ancestry\",\n            )?;\n            let headers = &headers_verification.value;\n            ancestry_cursor = *headers\n                .last()\n                .expect(\"nonempty ancestry window advances the cursor\");\n            finalized_headers.extend(headers.iter().copied());\n            connect_decisions.push(verification_decision(\n                &headers_verification,\n                Some(start),\n                Some(end),\n            ));\n        }\n        anyhow::ensure!(\n            ancestry_cursor == finalized,\n            \"Verified finalized header conflicts with its ancestry window\"\n        );\n        let nonce_verification = required_verification(\n            self.verification\n                .verify_transaction_count(&self.wallet_address, finalized.number)\n                .await,\n            \"Blockchain finalized transaction count\",\n        )?;\n        let observed_canonical_nonce = nonce_verification.value;\n        let next_canonical_nonce = position\n            .as_ref()\n            .map_or(observed_canonical_nonce, |position| {\n                position.next_canonical_nonce\n            });\n\n        if let Some(position) = position.as_ref() {\n            log::debug!(","sourceCodeStart":6023,"sourceCodeEnd":6059,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L6023-L6059","documentation":"After replaying the ancestry window of headers between the durable finalized tip and the newly verified finalized header, the cursor must land exactly on the verified finalized header. If it does not, one of the intermediate headers breaks the chain of ancestry (hash linkage), meaning the verified header is not a descendant of the stored tip.","triggerScenarios":"The while loop fetches consecutive header windows (verify via self.verification.verify_block / headers_verification decisions) from durable tip to finalized.number; the final ancestry_cursor != finalized, firing ensure!.","commonSituations":"A reorg replaced headers between the stored tip and the verified finalized height, an inconsistent verification provider returning headers that do not link, or corrupted cached headers within the ancestry window.","solutions":["Rebuild the finalized header ancestry from the trusted checkpoint to discard reorged/corrupt headers.","Verify the verification provider returns a consistent, hash-linked header chain (single provider, correct network).","Check for mid-window reorgs and restart connection once finality stabilizes above the affected heights.","Log/compare cursor hash vs finalized parent hash to locate the first divergent header before resyncing."],"exampleFix":"// before: alternating providers across ancestry windows can yield unlinked headers\nprovider = round_robin([rpc_a, rpc_b])\n\n// after: use one consistent provider per connect\nprovider = rpc_a","handlingStrategy":"validation","validationCode":"let linked = ancestry.windows(2).all(|w| w[1].parent_hash == w[0].hash());\nassert!(linked, \"ancestry window is not hash-linked\");","typeGuard":"fn ancestry_consistent(cursor: &Header, finalized: &Header) -> bool { cursor.hash() == finalized.hash() && cursor.number == finalized.number }","tryCatchPattern":"match client.connect().await {\n    Err(e) if e.to_string().contains(\"ancestry window\") => rebuild_ancestry_from_checkpoint().await,\n    other => other.map(|_| ()),\n}","preventionTips":["Use a single consistent verification provider per connect session","Validate parent-hash linkage of fetched headers incrementally","Rebuild ancestry from the trusted checkpoint after detected reorgs","Cache headers with integrity checks (hash verification on read)"],"tags":["blockchain","ancestry","consistency-check","reorg"],"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-14T05:17:10.506Z"}