nautechsystems/nautilus_trader · error · anyhow::Error
Persisted pool {pool_address} does not match restored pool {
Error message
Persisted pool {pool_address} does not match restored pool {} What it means
restore_swap_plan (crates/adapters/blockchain/src/execution/client.rs:865) resolves the pool for the intent's instrument via resolve_pool and requires the persisted intent's pool_address to equal it. A mismatch means the pool mapping configured in the restarted client differs from the pool the original swap actually routed through - completing reconciliation would attribute the swap to the wrong pool. The check keeps durable execution history consistent with live pool topology.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:865
"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(
intent
.amount_in
.as_deref()
.ok_or_else(|| anyhow::anyhow!("Persisted swap intent has no input amount"))?,
)?;
let fee = U24::try_from(
pool.fee
.ok_or_else(|| anyhow::anyhow!("Restored pool {instrument_id} has no fee"))?,
)?;
let quote_token = pool.get_quote_token();
let quote_currency = Currency::new_checked(
"e_token.symbol,
quote_token.decimals,View on GitHub (pinned to 2114cf6f76)
Solutions
- Compare the intent's pool_address with the pool your current configuration resolves for that instrument.
- Restore the pool mapping that was in effect when the swap was signed, reconnect, and let reconciliation complete.
- Once the intent is finalized, update configuration deliberately.
- Keep pool mappings deterministic (pin pool addresses in config) for any instrument with active intents.
Defensive patterns
Strategy: try-catch
Validate before calling
-- Pre-flight: compare each active intent's pool with your current mapping
SELECT i.id, i.instrument_id, i.pool_address, status
FROM execution_intent i
WHERE i.status IN ('prepared', 'signed', 'submitted')
AND i.purpose = 'swap';
-- verify each pool_address still equals the pool your config resolves for instrument_id Type guard
fn is_pool_mismatch(e: &anyhow::Error) -> bool {
e.to_string().contains("does not match restored pool")
} Try / catch
if let Err(e) = client.connect().await {
if is_pool_mismatch(&e) {
// pool topology changed under an active intent: restore the original mapping
// or resolve the intent on-chain before trading
log::error!("pool mapping conflicts with persisted swap intent: {e}");
}
return Err(e);
} Prevention
- Pin pool addresses deterministically in config instead of relying on discovery order.
- Freeze pool-mapping changes while any intent for the instrument is active.
- Diff pool mappings across restarts as part of deployment checks.
When it happens
Trigger: Pool discovery or allowlist configuration changed between the run that persisted the intent and the reconciling run (e.g. instrument now maps to a different pool address); a pool migrated/renumbered (fee tier change recorded as a different pool) while an old intent stayed active; duplicate pools for the same instrument with different mappings across configs.
Common situations: Editing pool allowlists or instrument-to-pool mappings between restarts; deployments that rediscover pools in a different order and pin different addresses.
Related errors
- Persisted swap trader does not match restored order
- Persisted swap strategy does not match restored order
- Persisted swap account does not match execution client accou
- Persisted swap instrument {instrument_id} does not match res
- Restored pool {instrument_id} has no fee
AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21).
Data as JSON: /api/errors/f4e62543dbb267fb.
Report an issue: GitHub.