nautechsystems/nautilus_trader · error

Finalized header conflicts with its verified ancestry

Error message

Finalized header conflicts with its verified ancestry

What it means

The client walks verified ancestry from the durable tip up to the finalized header and requires the cursor to land exactly on the finalized header. If the ancestry walk ends elsewhere, the claimed finalized header does not chain onto its own verified ancestry — a broken or forked link — so the finality claim is rejected.

Source

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

            let start = ancestry_cursor.number.saturating_add(1);
            let ancestry_verification = required_verification(
                self.verification
                    .verify_header_window(ancestry_cursor, end)
                    .await,
                "finality ancestry",
            )?;
            let ancestry = &ancestry_verification.value;
            ancestry_cursor = *ancestry
                .last()
                .expect("nonempty finality ancestry advances the cursor");
            decisions.push(verification_decision(
                &ancestry_verification,
                Some(start),
                Some(end),
            ));
            finalized_headers.extend(ancestry.iter().copied());
        }
        anyhow::ensure!(
            ancestry_cursor == finalized,
            "Finalized header conflicts with its verified ancestry"
        );

        let canonical_again_verification = required_verification(
            self.verification.verify_block(receipt.block_number).await,
            "finality inclusion header reread",
        )?;
        let canonical_again = canonical_again_verification.value;
        let finalized_again_verification = required_verification(
            self.verification.verify_block(finalized.number).await,
            "finalized header reread",
        )?;
        let finalized_again = finalized_again_verification.value;
        anyhow::ensure!(
            canonical_again.hash == receipt.block_hash && finalized_again == finalized,
            "Finality verification disagreed with the receipt or finalized header"
        );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Compare parent hashes along the walked ancestry to find the fork point.
  2. Re-fetch ancestry from the canonical provider and retry.
  3. Reset finality state to before the fork point and resync.

Example fix

// before: ancestry ends at a sibling header, not `finalized`
ensure!(ancestry_cursor == finalized, "Finalized header conflicts with its verified ancestry");
// after: detect fork point before walking
let fork = find_fork(&ancestry, &finalized)?;
if let Some(fork) = fork { resync_from(fork.number)?; }
Defensive patterns

Strategy: validation

Validate before calling

let fork = find_fork_point(&ancestry, &finalized)?;
anyhow::ensure!(fork.is_none(), "ancestry forks before finalized header");

Try / catch

match result {
    Err(e) if e.to_string().contains("conflicts with its verified ancestry") => {
        let fork = locate_fork()?;
        reset_finality_to(fork.number)?;
    }
    other => other,
}

Prevention

When it happens

Trigger: During ancestry construction: the loop from `durable_tip` toward `finalized.number` terminates but the final cursor header (`ancestry_cursor`) does not equal `finalized` — e.g. parent links in the fetched ancestry don't reach the finalized header (fork at some height within the range).

Common situations: Reorg inside the ancestry range while walking; provider returning headers from a fork; gaps or mismatched parent hashes in a custom verification source; fetching ancestry across an epoch boundary with a buggy provider.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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