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 intentView on GitHub (pinned to 18893faf8b)
Solutions
- Compare stored next_canonical_nonce vs observed_canonical_nonce to see the direction and size of divergence.
- 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.
- Reconcile against the chain: rebuild the ledger from the wallet's actual finalized nonce instead of trusting either divergent value.
- Check for out-of-band transactions from the same wallet (other bots, manual sends) and eliminate them.
- 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
- Never send transactions for a verification-managed wallet outside this system
- Reconcile the durable ledger against on-chain finalized nonces before restarts or restores
- When restoring database snapshots, quiesce the wallet first so the ledger and chain cannot diverge
- Double-check chain_id and wallet pairing when configuring the verification bootstrap
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
- Verified finalized transaction count advanced without an act
- Canonical nonce advanced without an authenticated signer tra
- Verified finalized header extension does not start at the du
- Finalized header ledger conflicts at height {}
- Execution nonce {} does not match canonical nonce {next_nonc
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/5a5bfbe2e552f4d7.
Report an issue: GitHub.