nautechsystems/nautilus_trader · error · anyhow::Error
Verified finality requires a finalized or reverted status
Error message
Verified finality requires a finalized or reverted status
What it means
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.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:6895
transaction
.commit()
.await
.map_err(|e| anyhow::anyhow!("Failed to commit execution transition: {e}"))?;
Ok(())
}
/// Records verified final consumption and advances the canonical nonce in one transaction.
///
/// # Errors
///
/// Returns an error if the receipt transition, nonce ledger, manifest identity, or evidence
/// is inconsistent, or if persistence fails.
pub(crate) async fn record_execution_finality_verified(
&self,
finality: &ExecutionFinalityTransition<'_>,
) -> anyhow::Result<()> {
anyhow::ensure!(
matches!(
finality.status,
TransactionStatus::Finalized | TransactionStatus::Reverted
),
"Verified finality requires a finalized or reverted status"
);
anyhow::ensure!(
!finality.decisions.is_empty(),
"Verified finality requires decision evidence"
);
anyhow::ensure!(
!finality.finalized_headers.is_empty()
&& finality.finalized_headers.windows(2).all(|headers| {
headers[1].number == headers[0].number.saturating_add(1)
&& headers[1].parent_hash == headers[0].hash
})
&& finality
.finalized_headersView on GitHub (pinned to 18893faf8b)
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.
Example fix
// before
let finality = ExecutionFinalityTransition { status: TransactionStatus::Confirmed, .. };
db.record_execution_finality_verified(&finality).await?;
// after
if matches!(finality.status, TransactionStatus::Finalized | TransactionStatus::Reverted) {
db.record_execution_finality_verified(&finality).await?;
} else {
tracing::debug!(status = finality.status.as_str(), "not final yet; deferring verified-finality record");
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: gate the call site on terminal statuses only
use crate::TransactionStatus;
fn is_verified_finality(s: &TransactionStatus) -> bool {
matches!(s, TransactionStatus::Finalized | TransactionStatus::Reverted)
} Type guard
fn is_terminal_status(s: &TransactionStatus) -> bool {
matches!(s, TransactionStatus::Finalized | TransactionStatus::Reverted)
}
if is_terminal_status(&finality.status) {
db.record_execution_finality_verified(&finality).await?;
} Try / catch
if let Err(e) = db.record_execution_finality_verified(&finality).await {
if e.to_string().contains("requires a finalized or reverted status") {
tracing::warn!(status = finality.status.as_str(), "premature finality record; deferring");
return Ok(()); // queue for later once finality is confirmed
}
return Err(e);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Intent cannot make the verified finality transition
- Unsupported `OrderSide` for Binance: {value:?}
- invalid OrderSide: must be Buy or Sell, was {side}
- Invalid execution transition for intent {intent_id}: {curren
- Finalized execution transaction {tx_hash} no longer has a re
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f6368f63d74e0da1.
Report an issue: GitHub.