nautechsystems/nautilus_trader · error
Pre-sign decision header does not extend the durable finaliz
Error message
Pre-sign decision header does not extend the durable finalized header tip
What it means
After loading the durable finalized tip from the ledger, the client requires it to sit within the verified window: at or after the trusted checkpoint and at or before the decision header. This proves the persisted ancestry baseline is usable to connect the checkpoint to the decision block. A tip outside that range indicates the ledger is stale (behind checkpoint) or corrupted/ahead (beyond the decision block), so the client aborts.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:2539
);
let mut decisions = vec![verification_decision(
&checkpoint,
Some(checkpoint.value.number),
Some(checkpoint.value.number),
)];
let wallet_address = self.wallet_address.to_string();
let position = self
.database
.load_execution_verification_position(
self.chain_id,
&wallet_address,
&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.value.number && durable_tip.number <= target.number,
"Pre-sign decision header does not extend the durable finalized header tip"
);
let durable_tip_verification = required_verification(
self.verification.verify_block(durable_tip.number).await,
"pre-sign durable finalized tip",
)?;
anyhow::ensure!(
durable_tip_verification.value == durable_tip,
"Durable finalized header tip conflicts with independent sources"
);
if durable_tip != checkpoint.value {
decisions.push(verification_decision(
&durable_tip_verification,
Some(durable_tip.number),
Some(durable_tip.number),
));View on GitHub (pinned to 18893faf8b)
Solutions
- Let the ledger catch up: run the header-verification/ledger advance loop until finalized_tip is >= checkpoint, then retry.
- Refresh the decision header/anchors so the decision block is at or after the durable tip.
- Inspect the ledger row for corruption or a wrong-lineage tip (e.g. after restoring a backup) and re-initialize if needed.
- Confirm the same (chain, wallet, manifest) identity is used by both the ledger writer and this signing client.
Example fix
// before: signing after long downtime without catching up the ledger let prepared = client.prepare_and_sign(intent).await?; // durable_tip.number < checkpoint.number // after: advance ledger to head first ledger.catch_up_to_finalized().await?; let prepared = client.prepare_and_sign(intent).await?;
Defensive patterns
Strategy: retry
Validate before calling
pub fn tip_in_window(tip_number: u64, checkpoint_number: u64, decision_number: u64) -> bool {
tip_number >= checkpoint_number && tip_number <= decision_number
} Try / catch
match prepare().await {
Err(e) if e.to_string().contains("does not extend the durable finalized header tip") => {
ledger.catch_up_to_finalized().await?;
prepare().await
}
other => other?,
} Prevention
- Keep the ledger advance loop running continuously; alert if it lags the checkpoint.
- After downtime, always catch the ledger up before resuming signing.
- Refresh decision headers when they may predate the durable tip.
When it happens
Trigger: Calling the pre-sign path when the persisted `finalized_tip` is older than the current verified checkpoint (ledger fell behind, e.g. after downtime) or newer than the decision header (decision header from stale anchors, or a corrupted/incorrectly parsed tip).
Common situations: Operator downtime during which the ledger stopped advancing while checkpoints moved on; database restored from an old backup; stale swap anchors making the decision header older than the durable tip; manifest rotation leaving the tip from another lineage.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Pre-sign decision header precedes the trusted checkpoint
- Canonical nonce ledger changed during verification bootstrap
- Finalized checkpoint ledger conflicts with the trusted chain
- Verified finalized headers do not start at the trusted check
- Verified finalized header ledger is not continuous
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ff90768d3dab4904.
Report an issue: GitHub.