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
- Check the node and verification source are on the same network and fork choice
- Update/re-sync the consensus checkpoint data
- Restart or resync the execution node if it followed a minority fork
- 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
- Ensure execution node and consensus source target the same network and fork
- Keep checkpoint data current
- Cross-check finalized hashes between two independent endpoints
- Halt finality-dependent actions on any disagreement rather than proceeding
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
- Finalized header verification is locally invalid
- Finalized execution transaction {tx_hash} no longer has a re
- Finalized block {} changed from {} to {} before intent valid
- Finalized block {} changed from {} to {} before fill emissio
- {context} verification disagreed
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/46cf55794654bbd7.
Report an issue: GitHub.