nautechsystems/nautilus_trader · critical
Finalized header verification is locally invalid
Error message
Finalized header verification is locally invalid
What it means
Same verification flow as the finalized-header disagreement case, but here the outcome is LocallyInvalid: the verified finalized header itself fails local validation (malformed or self-inconsistent data). The client bails because it cannot establish a trustworthy finalized height.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:3404
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),
Some(checkpoint.number),
)];
let position = selfView on GitHub (pinned to 18893faf8b)
Solutions
- Clear and rebuild the consensus/verification cache and retry
- Update the verification source/checkpoint data to the current network version
- Confirm the provider serves well-formed headers (compare against a second endpoint)
- Check the library version is compatible with the network's current header format
Example fix
// before: stale cached consensus data reused // after: force refresh of verification state before finality checks verification.refresh_checkpoints().await?; let finalized = verification.verify_finalized_header().await?;
Defensive patterns
Strategy: fallback
Validate before calling
let header = verification.verify_finalized_header().await?; debug_assert!(header.value.number > 0 && header.value.parent_hash != Default::default(), "malformed finalized header");
Try / catch
match res {
Err(e) if e.to_string().contains("locally invalid") => {
verification.rebuild_state().await?;
retry_verification().await?;
}
other => other?,
} Prevention
- Keep the consensus verification cache healthy and rebuildable
- Update library/checkpoint versions after network upgrades
- Validate headers against a second endpoint before trusting them
- Fail closed: never treat unverifiable finality as confirmed
When it happens
Trigger: verify_finalized_header() returns LocallyInvalid during the receipt finality check — typically corrupted or inconsistent header data from the verification source (bad fields, impossible values, failed local invariants).
Common situations: Corrupted local consensus data/cache; buggy or outdated verification source version; provider returning malformed headers after an upstream upgrade.
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 disagreed
- 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/d5ad8e5d6b609958.
Report an issue: GitHub.