{"record":{"id":"f6368f63d74e0da1","repo":"nautechsystems/nautilus_trader","slug":"verified-finality-requires-a-finalized-or-reverted","errorCode":null,"errorMessage":"Verified finality requires a finalized or reverted status","messagePattern":"Verified finality requires a finalized or reverted status","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":6895,"sourceCode":"\n        transaction\n            .commit()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to commit execution transition: {e}\"))?;\n        Ok(())\n    }\n\n    /// Records verified final consumption and advances the canonical nonce in one transaction.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the receipt transition, nonce ledger, manifest identity, or evidence\n    /// is inconsistent, or if persistence fails.\n    pub(crate) async fn record_execution_finality_verified(\n        &self,\n        finality: &ExecutionFinalityTransition<'_>,\n    ) -> anyhow::Result<()> {\n        anyhow::ensure!(\n            matches!(\n                finality.status,\n                TransactionStatus::Finalized | TransactionStatus::Reverted\n            ),\n            \"Verified finality requires a finalized or reverted status\"\n        );\n        anyhow::ensure!(\n            !finality.decisions.is_empty(),\n            \"Verified finality requires decision evidence\"\n        );\n        anyhow::ensure!(\n            !finality.finalized_headers.is_empty()\n                && finality.finalized_headers.windows(2).all(|headers| {\n                    headers[1].number == headers[0].number.saturating_add(1)\n                        && headers[1].parent_hash == headers[0].hash\n                })\n                && finality\n                    .finalized_headers","sourceCodeStart":6877,"sourceCodeEnd":6913,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L6877-L6913","documentation":"An upfront guard in record_execution_finality_verified: verified finality may only be recorded for TransactionStatus::Finalized or TransactionStatus::Reverted. Any other status (e.g. Pending, Processing, Confirmed) passed as finality means the caller is mislabeling a non-final receipt as verified finality, and the method refuses to persist it.","triggerScenarios":"Calling record_execution_finality_verified with an ExecutionFinalityTransition whose status is anything other than Finalized or Reverted — e.g. feeding a 'confirmed-but-not-finalized' receipt, or mapping a chain's receipt status into the wrong TransactionStatus variant.","commonSituations":"Chain reorg handling where a receipt is recorded before finality; misconfigured finality polling that fires at confirmation depth instead of finality; a node/provider emitting synthetic 'success' states not modeled as Finalized/Reverted; unit or integration tests passing a placeholder status.","solutions":["Only call this method once the provider reports the transaction as finalized (or reverted) — gate on the finality tracker's is_final signal.","Map chain-specific receipt states to TransactionStatus correctly before constructing ExecutionFinalityTransition.","Defer non-terminal receipts to the regular transition method instead of the verified-finality path.","Add a debug log of finality.status at call sites to catch status-mapping regressions."],"exampleFix":"// before\nlet finality = ExecutionFinalityTransition { status: TransactionStatus::Confirmed, .. };\ndb.record_execution_finality_verified(&finality).await?;\n// after\nif matches!(finality.status, TransactionStatus::Finalized | TransactionStatus::Reverted) {\n    db.record_execution_finality_verified(&finality).await?;\n} else {\n    tracing::debug!(status = finality.status.as_str(), \"not final yet; deferring verified-finality record\");\n}","handlingStrategy":"type-guard","validationCode":"// Rust: gate the call site on terminal statuses only\nuse crate::TransactionStatus;\nfn is_verified_finality(s: &TransactionStatus) -> bool {\n    matches!(s, TransactionStatus::Finalized | TransactionStatus::Reverted)\n}","typeGuard":"fn is_terminal_status(s: &TransactionStatus) -> bool {\n    matches!(s, TransactionStatus::Finalized | TransactionStatus::Reverted)\n}\n\nif is_terminal_status(&finality.status) {\n    db.record_execution_finality_verified(&finality).await?;\n}","tryCatchPattern":"if let Err(e) = db.record_execution_finality_verified(&finality).await {\n    if e.to_string().contains(\"requires a finalized or reverted status\") {\n        tracing::warn!(status = finality.status.as_str(), \"premature finality record; deferring\");\n        return Ok(()); // queue for later once finality is confirmed\n    }\n    return Err(e);\n}","preventionTips":["Wire record_execution_finality_verified only to the finality-confirmed callback, not the raw receipt handler.","Centralize chain receipt-status to TransactionStatus mapping in one tested function.","Add integration tests asserting non-terminal statuses never reach the finality path."],"tags":["validation","state-machine","finality","precondition"],"backgroundTag":"invalid-argument-value","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"}