{"record":{"id":"1db45a76830ae5b0","repo":"nautechsystems/nautilus_trader","slug":"retained-terminal-receipt-is-not-on-the-verified-f","errorCode":null,"errorMessage":"Retained terminal receipt is not on the verified finalized ancestry","messagePattern":"Retained terminal receipt is not on the verified finalized ancestry","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":5513,"sourceCode":"                            format!(\n                                \"Retained transaction hash {} is invalid\",\n                                current.transaction_hash\n                            )\n                        },\n                    )?)\n                    .await,\n                \"migration receipt\",\n            )?;\n            let receipt = receipt_verification.value.clone();\n            anyhow::ensure!(\n                receipt.block_number <= finalized.number,\n                \"Retained terminal receipt is above the verified finalized boundary\"\n            );\n            let inclusion_verification = required_verification(\n                self.verification.verify_block(receipt.block_number).await,\n                \"migration inclusion header\",\n            )?;\n            anyhow::ensure!(\n                inclusion_verification.value.hash == receipt.block_hash\n                    && finalized_headers.iter().any(|header| {\n                        header.number == receipt.block_number\n                            && header.hash == receipt.block_hash.to_string()\n                    }),\n                \"Retained terminal receipt is not on the verified finalized ancestry\"\n            );\n            let tx_hash = B256::from_str(&current.transaction_hash)\n                .context(\"Retained transaction hash is invalid\")?;\n            let included = IncludedTransaction {\n                intent_id: intent.id,\n                nonce,\n                tx_hash,\n                block_number: receipt.block_number,\n                receipt: receipt.clone(),\n                finality: StableFinality {\n                    decisions: Vec::new(),\n                    inclusion_header: durable_verified_header(&inclusion_verification.value),","sourceCodeStart":5495,"sourceCodeEnd":5531,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L5495-L5531","documentation":"During a migration of terminal execution receipts, the client verifies that a retained terminal receipt actually sits on the chain's verified finalized header ancestry. It fetches an inclusion header via the verification service and checks that the header hash matches the receipt's block hash and that a finalized header with the same number/hash exists in the fetched ancestry. This guards against retaining receipts for orphaned or reorged-out blocks as the terminal state.","triggerScenarios":"Running the receipt-migration path where a stored terminal receipt references a block_hash/number that is either not on the finalized ancestry (orphaned block, chain reorg) or where verify_block returns a header whose hash no longer matches the stored block_hash.","commonSituations":"A node that followed a minority fork or was reorged; a receipt persisted before a deep reorg; corrupted or hand-edited durable state; running the migration against a different network than the one that produced the receipt.","solutions":["Verify the receipt's block_hash/number against a trusted RPC/explorer and confirm the block is finalized on the current chain","Purge or re-derive the retained terminal receipt from durable storage so migration re-fetches a valid one","Ensure the verification service/endpoint points at the same chain (correct network_id/chain id) as the receipt","Re-run the migration after the node has fully caught up and finalized blocks"],"exampleFix":"// before (stale/orphaned receipt in durable store)\nreceipt = ExecutionReceipt { block_number: 1001, block_hash: 0xaaa... }\n// after (re-derived from finalized chain)\nreceipt = fetch_finalized_receipt(block_number: 1001) // hash now matches finalized ancestry 0xbbb...","handlingStrategy":"validation","validationCode":"// before running migration, confirm the receipt block is finalized on the current chain\nlet header = verification.verify_block(receipt.block_number).await?;\nassert_eq!(header.value.hash, receipt.block_hash, \"receipt block not on current chain\");\nassert!(header.value.status.is_finalized(), \"receipt block not finalized\");","typeGuard":"fn is_on_finalized_ancestry(receipt: &Receipt, headers: &[Header]) -> bool {\n    headers.iter().any(|h| h.number == receipt.block_number && h.hash == receipt.block_hash.to_string())\n}","tryCatchPattern":"match run_migration().await {\n    Err(e) if e.to_string().contains(\"not on the verified finalized ancestry\") => {\n        purge_stale_receipt(&receipt_id)?; // re-derive from finalized chain\n    }\n    Err(e) => return Err(e),\n    Ok(r) => Ok(r),\n}","preventionTips":["Verify receipts against a trusted finalized block source before persisting them as terminal","Pin the verification endpoint to the same chain/network as the receipts","Watch for reorgs (hash changes at a given height) and invalidate stored receipts when detected","Never hand-edit durable receipt records; use the client's repair paths"],"tags":["blockchain","finality","migration","consistency"],"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"}