nautechsystems/nautilus_trader · critical

Finalized header verification disagreed

Error message

Finalized header verification disagreed

What it means

The consensus verification layer returned VerificationOutcome::Disagreement for the finalized header check: the locally computed/verified finalized header conflicts with the authoritative source. The client treats this as a hard failure — it cannot trust the finalized chain view for receipt finality decisions.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:3401

                None,
            )
            .await?;
        Ok(InclusionOutcome::Pending(format!(
            "Timed out awaiting finality of transaction {tx_hash}; the intent stays occupied for reconciliation"
        )))
    }

    async fn receipt_is_stably_finalized(
        &self,
        receipt: &RpcTransactionReceipt,
    ) -> anyhow::Result<Option<StableFinality>> {
        let finalized_verification = match self.verification.verify_finalized_header().await {
            VerificationOutcome::Verified(verified) => verified,
            VerificationOutcome::Retryable(_) | VerificationOutcome::Unavailable(_) => {
                return Ok(None);
            }
            VerificationOutcome::Disagreement(_) => {
                anyhow::bail!("Finalized header verification disagreed")
            }
            VerificationOutcome::LocallyInvalid(_) => {
                anyhow::bail!("Finalized header verification is locally invalid")
            }
        };
        let finalized = finalized_verification.value;
        if finalized.number < receipt.block_number {
            return Ok(None);
        }

        let checkpoint_verification = required_verification(
            self.verification.verify_checkpoint().await,
            "finality checkpoint reread",
        )?;
        let checkpoint = checkpoint_verification.value;
        let mut decisions = vec![verification_decision(
            &checkpoint_verification,
            Some(checkpoint.number),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the node and verification source are on the same network and fork choice
  2. Update/re-sync the consensus checkpoint data
  3. Restart or resync the execution node if it followed a minority fork
  4. Verify provider configuration (correct chain, no caching proxy serving stale headers)

Example fix

// before: mismatched endpoints
let exec = ExecutionClient::new(exec_rpc, verify_source_for_testnet);
// after: consistent chain sources
let exec = ExecutionClient::new(exec_rpc, verify_source_for_mainnet);
Defensive patterns

Strategy: fallback

Validate before calling

let local_finalized = rpc.finalized_block().await?;
let verified = verification.verify_finalized_header().await?;
assert_eq!(local_finalized.hash, verified.value.hash, "finalized header mismatch");

Try / catch

match res {
    Err(e) if e.to_string().contains("verification disagreed") => {
        halt_trading(); // do not act on untrusted finality
        alert_consensus_divergence();
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling the finalized-receipt verification flow when verify_finalized_header() yields a Disagreement — consensus checkpoint mismatch, divergent fork, or the verification source disagrees with the node's finalized block.

Common situations: Node syncing to a different fork; misconfigured consensus/checkpoint source; provider serving a chain that disagrees with the light-client verification data; mixed network endpoints (mainnet vs testnet).

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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