nautechsystems/nautilus_trader · error
Retained execution intent belongs to another signer
Error message
Retained execution intent belongs to another signer
What it means
Each retained execution intent is validated against the current client's chain ID and configured wallet address before its history is replayed. This error is thrown when the snapshot was created for a different chain or a different wallet, meaning the stored intents do not belong to this signer and cannot be safely resumed.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:5336
let active_count = snapshot
.intents
.iter()
.filter(|intent| intent.active)
.count();
anyhow::ensure!(
active_count <= 1,
"Retained execution history has multiple active signer owners"
);
let mut nonce_owners = HashMap::new();
let mut records = Vec::with_capacity(snapshot.intents.len());
let finalized_headers = finalized_headers
.iter()
.map(durable_verified_header)
.collect::<Vec<_>>();
for intent in &snapshot.intents {
anyhow::ensure!(
intent.chain_id == self.chain.chain_id
&& intent.wallet_address == self.config.wallet_address,
"Retained execution intent belongs to another signer"
);
let purpose = TransactionPurpose::parse(&intent.purpose).ok_or_else(|| {
anyhow::anyhow!("Retained execution intent has an unsupported purpose")
})?;
let hashes = hashes_by_intent
.get(&intent.id)
.map(Vec::as_slice)
.unwrap_or_default();
let current = hashes
.iter()
.copied()
.filter(|hash| hash.current)
.collect::<Vec<_>>();
anyhow::ensure!(
current.len() <= 1,View on GitHub (pinned to 18893faf8b)
Solutions
- Move or delete the stale execution snapshot so the client rebuilds state for the current chain/wallet (after confirming no pending on-chain transactions)
- Fix the config so chain_id and wallet_address match the deployment that produced the snapshot
- Keep per-chain, per-wallet data directories so snapshots are never reused across deployments
Example fix
// before wallet_address = "0xOLD" # reuses old snapshot dir // after wallet_address = "0xNEW" mv data/execution data/execution.old-0xOLD # fresh snapshot for new signer
Defensive patterns
Strategy: validation
Validate before calling
fn snapshot_matches(snapshot: &ExecutionSnapshot, chain_id: u64, wallet: Address) -> bool {
snapshot.intents.iter().all(|i| i.chain_id == chain_id && i.wallet_address == wallet)
} Try / catch
match client.start_with_snapshot(snapshot) {
Err(e) if e.to_string().contains("belongs to another signer") => { /* archive snapshot, confirm no pending tx, rebuild */ }
other => other?,
} Prevention
- Scope durable state directories per (chain_id, wallet_address)
- Diff config chain/wallet against snapshot metadata at startup before loading
- Never copy execution state between testnet and mainnet deployments
When it happens
Trigger: Starting the execution client with a snapshot whose intent.chain_id != self.chain.chain_id or intent.wallet_address != self.config.wallet_address.
Common situations: Pointing the client at a new RPC chain/chain ID while reusing an old data directory; changing WALLET_ADDRESS in config without clearing retained state; copying state files between deployments (testnet snapshot used on mainnet).
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
- Verification chain anchor ID does not match the configured c
- Persisted transaction row chain ID {} does not match configu
- Verified chain ID does not match the transaction chain
- Retained execution history has multiple active signer owners
- Retained execution intent {} has multiple current hashes
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e7401e0e6cbb5dbe.
Report an issue: GitHub.