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(
            &quote_token.symbol,
            quote_token.decimals,

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Compare the intent's pool_address with the pool your current configuration resolves for that instrument.
  2. Restore the pool mapping that was in effect when the swap was signed, reconnect, and let reconciliation complete.
  3. Once the intent is finalized, update configuration deliberately.
  4. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/f4e62543dbb267fb. Report an issue: GitHub.