nautechsystems/nautilus_trader · error
Canonical nonce {} is outside the owned reconciliation range
Error message
Canonical nonce {} is outside the owned reconciliation range {}..={next_nonce} What it means
During rebroadcast reconciliation, the execution client re-fetches the wallet's canonical (mined) transaction count and the pending transaction count, and ensures both fall within the nonce range owned by the prepared transaction (prepared.nonce..=prepared.nonce+1). If the chain reports a canonical nonce outside this tiny window, the wallet's on-chain state has diverged from the client's local in-flight transaction, so it refuses to authorize the rebroadcast rather than broadcast a duplicate or stale transaction.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:2922
let receipt_absence = required_verification(
self.verification
.verify_receipt_absence(&prepared.tx_hash)
.await,
"rebroadcast receipt absence",
)?;
decisions.push(verification_decision(&receipt_absence, None, None));
let next_nonce = prepared
.nonce
.checked_add(1)
.ok_or_else(|| anyhow::anyhow!("Owned signer nonce overflow"))?;
anyhow::ensure!(
(prepared.nonce..=next_nonce).contains(&pending_nonce.value),
"Pending nonce {} is outside the owned reconciliation range {}..={next_nonce}",
pending_nonce.value,
prepared.nonce
);
anyhow::ensure!(
(prepared.nonce..=next_nonce).contains(&canonical_nonce.value),
"Canonical nonce {} is outside the owned reconciliation range {}..={next_nonce}",
canonical_nonce.value,
prepared.nonce
);
if !receipt_absence.value {
self.persist_rebroadcast_decisions(intent.id, prepared.nonce, &decisions)
.await?;
return Ok(ReconciliationAuthorization::Retain);
}
if canonical_nonce.value == next_nonce {
self.persist_rebroadcast_decisions(intent.id, prepared.nonce, &decisions)
.await?;
return Ok(ReconciliationAuthorization::ScanReplacement(
decision_header.value,
));View on GitHub (pinned to 18893faf8b)
Solutions
- Stop all other senders using this wallet so this client is the sole nonce owner
- Check the reported canonical nonce: if it equals prepared.nonce+1 the transaction was mined — let reconciliation retain rather than rebroadcast
- Reset the client's local nonce from the chain's latest transaction count and re-prepare the transaction
- Verify the RPC endpoint targets the intended chain_id and a consistent node
Example fix
// before let prepared = client.prepare_transaction(intent); // stale local nonce // after let onchain_nonce = client.transaction_count(wallet).await; let prepared = client.prepare_transaction_with_nonce(intent, onchain_nonce);
Defensive patterns
Strategy: validation
Validate before calling
let canonical = client.transaction_count(wallet).await?;
let pending = client.pending_count(wallet).await?;
let next = prepared.nonce.checked_add(1).expect("nonce overflow");
if !(prepared.nonce..=next).contains(&canonical) || !(prepared.nonce..=next).contains(&pending) {
return Err("nonce window mismatch; resync local nonce from chain");
} Prevention
- Use a single nonce owner per wallet key
- Refresh local nonce from the chain before preparing transactions
- Pin to one consistent RPC endpoint
- Track and persist in-flight nonces across restarts
When it happens
Trigger: authorize_rebroadcast() was called for a PreparedTransaction whose nonce no longer matches the chain's transaction_count for the wallet: e.g. another process/wallet instance already broadcast and mined a transaction with a different nonce, the local nonce bookkeeping drifted, or a replacement transaction with an unrelated nonce was mined in between.
Common situations: Running two executors against the same wallet key; manual transactions sent from the wallet out-of-band; restarting the client after nonce state was lost; an RPC endpoint behind a load balancer returning inconsistent nonces; replaying intents prepared against a different chain state.
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
- Canonical nonce advanced without an authenticated signer tra
- Finalized execution transaction {tx_hash} no longer has a re
- Canonical head changed during signer-nonce replacement scan
- Finalized block {} changed from {} to {} before intent valid
- Finalized transaction {} emitted {} Swap logs; expected exac
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/27beb18b053c473c.
Report an issue: GitHub.