nautechsystems/nautilus_trader · error

Execution verification ledger is not initialized

Error message

Execution verification ledger is not initialized

What it means

`verify_decision_ancestry` loads the durable execution verification position (the persisted finalized header tip) from the database for this chain/wallet/manifest. If no row exists, the verification ledger was never initialized, so there is no durable ancestry baseline and the client aborts the pre-sign flow.

Source

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

            checkpoint.value.number <= target.number,
            "Pre-sign decision header precedes the trusted checkpoint"
        );
        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),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Run the ledger initialization/bootstrap step for the configured chain, wallet, and manifest before signing transactions.
  2. Verify the client config (chain_id, wallet_address, manifest_version, manifest_digest) matches an initialized ledger row.
  3. Check the client is connected to the intended database (wrong env: staging vs production).
  4. If the manifest was rotated, initialize the new manifest's ledger position before resuming signing.

Example fix

// before: signing immediately after deploy with a fresh DB
let prepared = client.prepare_and_sign(intent).await?; // no ledger row for manifest v2
// after: initialize first
initializer.init_execution_verification_ledger(chain_id, &wallet, "v2", &manifest_digest).await?;
let prepared = client.prepare_and_sign(intent).await?;
Defensive patterns

Strategy: validation

Validate before calling

pub async fn ledger_ready(db: &Database, chain_id: i64, wallet: &str, manifest_version: &str, digest: &str) -> anyhow::Result<bool> {
    Ok(db.load_execution_verification_position(chain_id, wallet, manifest_version, digest).await?.is_some())
}

Try / catch

match client.prepare_and_sign(intent).await {
    Err(e) if e.to_string().contains("ledger is not initialized") => {
        init_ledger(cfg).await?;
        client.prepare_and_sign(intent).await
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling the transaction preparation path against a database that has no `execution_verification_position` record for the configured (chain_id, wallet_address, manifest_version, manifest_digest) tuple — first run without running ledger initialization, or a config change (new manifest version/digest, different wallet or chain) that keys a nonexistent ledger entry.

Common situations: Fresh deployment where the bootstrap/initialization step was skipped; rotating the deployment manifest version without re-initializing the ledger; pointing the client at the wrong database/chain id; wiping the database while keeping runtime state.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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