nautechsystems/nautilus_trader · critical
Canonical nonce advanced without an authenticated signer tra
Error message
Canonical nonce advanced without an authenticated signer transaction in the canonical range
What it means
The client tracks the signer account's nonce against the chain's canonical head. This error is thrown when the canonical nonce has advanced to a value higher than what this client last authenticated, yet no transaction signed by this signer was found within the canonical block range it inspected. It is a safety check against nonce drift — the account moved without a locally-verifiable cause, so the client refuses to proceed with stale nonce assumptions.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:3193
wallet_address: &wallet_address,
nonce,
finalized_cursor: finalized_cursor.as_ref(),
matched_transaction_hash: matched_hash.as_deref(),
manifest_version: &self.manifest_version,
manifest_digest: &self.manifest_digest,
provider_ids: &self.provider_ids,
operator_ids: &self.operator_ids,
failure_domain_ids: &self.failure_domain_ids,
decisions: &decisions,
})
.await?;
if let Some(e) = mismatch {
return Err(e);
}
if matched.is_none() && end == head.number {
anyhow::bail!(
"Canonical nonce advanced without an authenticated signer transaction in the canonical range"
);
}
Ok(matched)
}
async fn persist_rebroadcast_decisions(
&self,
intent_id: i64,
nonce: u64,
decisions: &[ExecutionVerificationDecision],
) -> anyhow::Result<()> {
let wallet_address = self.wallet_address.to_string();
self.database
.record_execution_verification_batch(&ExecutionVerificationBatch {
intent_id,
chain_id: self.chain_id,
wallet_address: &wallet_address,View on GitHub (pinned to 18893faf8b)
Solutions
- Pause submissions for this signer and re-sync the nonce from the chain before resuming
- Audit for other processes or wallets using the same signer key and stop the contention
- Wait for the canonical range to include the missing signer transaction, or wait for chain head to stabilize after a reorg
- Restart the client so the nonce cache is rebuilt from the current canonical state
Example fix
// before: resubmitting immediately after nonce error submit_trade(plan).await?; // after: resync nonce and confirm no external signer activity let nonce = client.fetch_account_nonce(signer).await?; client.reset_cached_nonce(signer, nonce).await?; submit_trade(plan).await?;
Defensive patterns
Strategy: retry
Validate before calling
let chain_nonce = client.fetch_account_nonce(signer).await?; assert_eq!(chain_nonce, client.cached_nonce(signer), "nonce drifted; resync before submitting");
Try / catch
match res {
Err(e) if e.to_string().contains("Canonical nonce advanced") => {
client.resync_nonce(signer).await?;
retry_later();
}
other => other?,
} Prevention
- Use a dedicated signer key per client instance
- Never send funds from the trading hot wallet manually
- Monitor nonce drift with an alert on external nonce changes
- Resync the nonce from chain before each submission batch
When it happens
Trigger: Calling transaction submission or nonce-verification paths (the function returning the matched canonical nonce) when: the signer sent transactions from another client/wallet, a transaction was replaced or reorged out of the canonical range, or the local nonce cache is behind the chain head with no authenticated tx found between the tracked range and head.number.
Common situations: Shared signing key used by multiple services or bots; manual transfers from the same hot wallet; a chain reorg removing the tx that justified the nonce bump; running a second instance of the trader against the same key; provider switching between endpoints with divergent views of the head.
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Verified finalized transaction count advanced without an act
- Verified finalized transaction count is outside the owned re
- Canonical nonce {} is outside the owned reconciliation range
- Canonical head changed during signer-nonce replacement scan
- RPC tick {tick_value} does not match positions: derived gros
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/24b4a1dcbc7156c5.
Report an issue: GitHub.