nautechsystems/nautilus_trader · error

Durable finalized header tip precedes the trusted checkpoint

Error message

Durable finalized header tip precedes the trusted checkpoint

What it means

The execution client recovered its durable finalized tip from the verification ledger, but the stored header's block number is lower than the trusted checkpoint the run is anchored to. NautilusTrader requires durable finality to be at least as advanced as the checkpoint, so a stale or rolled-back ledger means the durable state cannot safely supplement checkpoint trust and the operation is aborted.

Source

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

        )?;
        let checkpoint = checkpoint_verification.value;
        let mut decisions = vec![verification_decision(
            &checkpoint_verification,
            Some(checkpoint.number),
            Some(checkpoint.number),
        )];
        let position = self
            .database
            .load_execution_verification_position(
                self.chain_id,
                &self.wallet_address.to_string(),
                &self.manifest_version,
                &self.manifest_digest,
            )
            .await?
            .ok_or_else(|| anyhow::anyhow!("Execution verification ledger is not initialized"))?;
        let durable_tip = parse_verified_header(&position.finalized_tip)?;
        anyhow::ensure!(
            durable_tip.number >= checkpoint.number,
            "Durable finalized header tip precedes the trusted checkpoint"
        );
        let mut finalized_headers = vec![durable_tip];
        let durable_tip_verification = required_verification(
            self.verification.verify_block(durable_tip.number).await,
            "finality durable header tip",
        )?;
        anyhow::ensure!(
            durable_tip_verification.value == durable_tip,
            "Durable finalized header tip conflicts with independent sources"
        );
        decisions.push(verification_decision(
            &durable_tip_verification,
            Some(durable_tip.number),
            Some(durable_tip.number),
        ));
        anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the verification ledger's finalized tip and compare its block number to the configured trusted checkpoint.
  2. Rebuild or resync the verification ledger so its finalized tip is at or beyond the checkpoint (e.g. replay finalized headers from the RPC provider).
  3. Re-run the recovery after the ledger has caught up, or re-anchor the run at an older checkpoint consistent with the ledger.

Example fix

// before: checkpoint ahead of ledger state
let checkpoint = load_checkpoint(); // # 1_000
// ledger finalized_tip.number == 900 -> ensure! fails
// after: resync ledger, then verify before recovery
ensure_durable_tip_covers_checkpoint(&ledger, &checkpoint)?; // tip >= checkpoint
Defensive patterns

Strategy: validation

Validate before calling

// before recovery, assert ledger covers checkpoint
let tip_number = ledger.finalized_tip_number()?;
anyhow::ensure!(tip_number >= checkpoint.number, "ledger tip {} < checkpoint {}", tip_number, checkpoint.number);

Try / catch

match client.recover_finality(&checkpoint).await {
    Err(e) if e.to_string().contains("precedes the trusted checkpoint") => resync_ledger_and_retry(),
    Err(e) => return Err(e),
    Ok(v) => Ok(v),
}

Prevention

When it happens

Trigger: Calling transaction finality recovery when the verification ledger row `finalized_tip` holds a header whose number < the checkpoint number — typically after restoring an older ledger snapshot, a partial ledger write/rollback, or pointing the client at a database populated against a different (older) checkpoint.

Common situations: Failover to a replica with a lagging verification ledger; restoring a DB backup from before the checkpoint was advanced; mixing ledger state from a previous deployment with a newer configured trusted checkpoint; ledger pruning that removed recent finalized headers.

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/3d43df7df218303d. Report an issue: GitHub.