nautechsystems/nautilus_trader · error · anyhow::Error

Verified finalized transaction count is outside the owned re

Error message

Verified finalized transaction count is outside the owned recovery range

What it means

During bootstrap of an initialized signer, the observed canonical nonce (verified finalized transaction count) must equal either the stored ledger nonce or exactly stored_nonce + 1 (crates/adapters/blockchain/src/cache/database.rs:4041). Any other relationship — advanced by more than one, or the observed count being behind the ledger — means the durable canonical nonce and the verified finalized count have diverged beyond the single sanctioned recovery step, so bootstrap aborts.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:4041

            anyhow::ensure!(
                bootstrap.migration.is_none(),
                "Verification migration was supplied for an initialized signer"
            );
            anyhow::ensure!(
                manifest_version == bootstrap.manifest_version
                    && manifest_digest == bootstrap.manifest_digest,
                "Execution verification manifest identity changed"
            );
            anyhow::ensure!(
                stored_nonce == next_canonical_nonce,
                "Canonical nonce ledger changed during verification bootstrap"
            );

            if observed_canonical_nonce != stored_nonce {
                let expected_observed_nonce = stored_nonce
                    .checked_add(1)
                    .ok_or_else(|| anyhow::anyhow!("Canonical nonce overflow"))?;
                anyhow::ensure!(
                    observed_canonical_nonce == expected_observed_nonce,
                    "Verified finalized transaction count is outside the owned recovery range"
                );
                let recovery = sqlx::query_as::<_, (Option<i64>, String, i64)>(
                    "
                    SELECT
                        intent.nonce,
                        intent.status,
                        COUNT(hash.id) FILTER (
                            WHERE hash.current
                              AND hash.payload_expected
                              AND ((hash.raw_transaction IS NOT NULL)::INTEGER
                                   + (hash.sealed_transaction IS NOT NULL)::INTEGER) = 1
                              AND hash.status IN (
                                  'broadcast', 'included', 'replaced', 'dropped', 'reorged'
                              )
                        )
                    FROM execution_intent AS intent

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Compare stored next_canonical_nonce vs observed_canonical_nonce to see the direction and size of divergence.
  2. If the ledger is behind, ensure exactly one in-flight owned intent at the durable nonce exists (the code requires one recoverable retained payload) and re-run bootstrap; this error itself means the recovery-range guard failed, so fix the divergence first.
  3. Reconcile against the chain: rebuild the ledger from the wallet's actual finalized nonce instead of trusting either divergent value.
  4. Check for out-of-band transactions from the same wallet (other bots, manual sends) and eliminate them.
  5. Verify the correct chain_id/wallet pairing is being bootstrapped.

Example fix

// before
// observed nonce jumped by 3 due to out-of-band sends from the same wallet
bootstrap(chain_id, wallet, next_canonical_nonce, observed = stored + 3)?;

// after
// stop out-of-band senders, reconcile ledger with on-chain finalized nonce, then bootstrap with the reconciled count
let reconciled = db.reconcile_canonical_nonce_from_chain(chain_id, wallet).await?;
bootstrap(chain_id, wallet, reconciled.next_canonical_nonce, reconciled.observed).await?;
Defensive patterns

Strategy: validation

Validate before calling

let observed = count_verified_finalized(chain_id, wallet)?;
let stored = fetch_stored_nonce(chain_id, wallet)?;
if observed != stored && observed != stored.checked_add(1).ok_or(anyhow::anyhow!("overflow"))? {
    return Err(anyhow::anyhow!("observed nonce {observed} diverges from ledger {stored}; reconcile before bootstrap"));
}

Try / catch

match bootstrap_verification(...).await {
    Err(e) if e.to_string().contains("outside the owned recovery range") => {
        // reconcile canonical nonce from on-chain finalized transactions, then retry bootstrap
    }
    other => other?,
}

Prevention

When it happens

Trigger: Observed canonical nonce differs from the stored next_canonical_nonce by more than +1, or is smaller than the stored value — e.g. transactions finalized outside the tracked ledger, a restored database under a wallet that kept transacting, or an incorrect observed count computed from a partial verification scan.

Common situations: Restoring an old database snapshot while the wallet continued trading on-chain; multiple writers sending transactions for the same wallet outside this system; reorg/finality miscount making the observed count jump or lag; pointing the bootstrap at the wrong chain_id so counts don't line up.

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


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