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_headers

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Only call this method once the provider reports the transaction as finalized (or reverted) — gate on the finality tracker's is_final signal.
  2. Map chain-specific receipt states to TransactionStatus correctly before constructing ExecutionFinalityTransition.
  3. Defer non-terminal receipts to the regular transition method instead of the verified-finality path.
  4. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/f6368f63d74e0da1. Report an issue: GitHub.