nautechsystems/nautilus_trader · error · anyhow::Error

Persisted pool does not match restored pool

Error message

Persisted pool {pool_address} does not match restored pool {}

What it means

After parsing the persisted pool_address, restore_swap_plan resolves the pool for the intent's instrument via resolve_pool and compares its on-chain address with the persisted one. If the registered/restored pool for that instrument has a different address than what the intent was prepared against, the client aborts reconciliation. This guarantees the swap is replayed against exactly the pool it was originally created for, guarding against instrument remapping to a different pool contract.

Solutions

  1. Restore the original pool/instrument registration so resolve_pool returns the pool address stored in the intent.
  2. Resolve or cancel the pending intent before changing pool configuration, then re-issue the trade.
  3. Verify chain_id and network configuration match the environment where the intent was persisted.
  4. Inspect the intent row and current instrument definition to confirm which is stale, and fix the stale side.
Defensive patterns

Strategy: validation

Validate before calling

let pool = client.resolve_pool(&instrument_id)?;
if pool.address != intent_pool_address {
    eprintln!("pool for {instrument_id} changed since intent was written; restore original registration or cancel the intent");
}

Type guard

fn pool_matches(pool: &Pool, persisted: Address) -> bool {
    pool.address == persisted
}

Prevention

When it happens

Trigger: reconcile_unresolved_execution or build_execution_verification_migration calls restore_swap_plan on an intent whose persisted pool_address differs from the address of the pool resolved for intent.instrument_id. Occurs when the instrument's pool registration changed between persisting and restoring (different DEX/pool configured), or the intent belongs to a different chain/fork with a same-instrument but different pool.

Common situations: Changing the pool/instrument definition (e.g. new pool deployment, different fee tier) while an old swap intent was still pending; pointing the node at a different chain or forked network with different contract addresses; loading another environment's database.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at crates/adapters/blockchain/src/execution/client.rs:1069

            "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 18893faf8b)