nautechsystems/nautilus_trader · error · anyhow::Error
Persisted swap account does not match execution client…
Error message
Persisted swap account does not match execution client account
What it means
restore_swap_plan verifies that the account_id persisted on the execution intent matches the account_id of this execution client (self.core.account_id). A mismatch means the durable swap intent was written by a different execution client account (e.g. another wallet or venue account), so reconciliation refuses to restore and re-drive the swap. This stops swaps belonging to one account from being executed by another.
Solutions
- Configure the execution client with the same account_id that persisted the intents (revert wallet/account changes or use the original database).
- Separate durable stores per account so intents are never shared across accounts.
- Resolve or clear the pending intent in the durable store before switching accounts.
- Verify cache/database wiring so the node connects to the store belonging to the configured account.
Example fix
// before account_id = "BLOCKCHAIN-0xNewWallet" // after (account that wrote the intents) account_id = "BLOCKCHAIN-0xOriginalWallet"
Defensive patterns
Strategy: validation
Validate before calling
if intent.account_id.as_deref() != Some(exec_client_account_id.as_str()) {
eprintln!("persisted intent belongs to a different account; align account_id config or use the original database");
} Type guard
fn account_matches(intent: &ExecutionIntentRow, client_account_id: &AccountId) -> bool {
intent.account_id.as_deref() == Some(client_account_id.as_str())
} Prevention
- Keep wallet/account_id stable; rotate only after all intents are resolved
- Use one durable store per account
- Verify DB wiring matches the configured account before connect
- Inspect account_id on persisted rows when migrating environments
When it happens
Trigger: reconcile_unresolved_execution or build_execution_verification_migration restores an ExecutionIntentRow whose intent.account_id is None or differs from self.core.account_id during restore_swap_plan. Happens when the execution client's account (wallet/venue account id) changed between runs, or the durable store contains intents from another account.
Common situations: Rotating wallet or changing account_id config while intents were pending; pointing one node at another account's database; running multiple execution clients (different accounts) against a shared durable store; old rows with NULL account_id.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Persisted swap strategy does not match restored order
- Persisted swap trader does not match restored order
- account ID differs across fill group
- Execution intent has no persisted signed transaction bytes
- Execution mass status account ID
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/777df2cfb4e1d9da.
Report an issue: GitHub.
Appendix: source
Thrown at crates/adapters/blockchain/src/execution/client.rs:1057
intent
.instrument_id
.as_deref()
.ok_or_else(|| anyhow::anyhow!("Persisted swap intent has no instrument ID"))?,
)?;
anyhow::ensure!(
order.instrument_id() == instrument_id,
"Persisted swap instrument {instrument_id} does not match restored order instrument {}",
order.instrument_id()
);
anyhow::ensure!(
intent.trader_id.as_deref() == Some(order.trader_id().as_str()),
"Persisted swap trader does not match restored order"
);
anyhow::ensure!(
intent.strategy_id.as_deref() == Some(order.strategy_id().as_str()),
"Persisted swap strategy does not match restored order"
);
anyhow::ensure!(
intent.account_id.as_deref() == Some(self.core.account_id.as_str()),
"Persisted swap account does not match execution client account"
);
let pool = self.resolve_pool(&instrument_id)?;
let pool_address = Address::from_str(
intent
.pool_address
.as_deref()
.ok_or_else(|| anyhow::anyhow!("Persisted swap intent has no pool address"))?,
)?;
anyhow::ensure!(
pool.address == pool_address,
"Persisted pool {pool_address} does not match restored pool {}",
pool.address
);
let amount_in = U256::from_str(
intentView on GitHub (pinned to 18893faf8b)