nautechsystems/nautilus_trader · error · anyhow::Error

Cached pool {} does not match its deployment manifest identi

Error message

Cached pool {} does not match its deployment manifest identity

What it means

In `validate_manifest_pool` (crates/adapters/blockchain/src/execution/client.rs:4135), after resolving the manifest entry, its token0/token1 addresses, fee, and factory are compared against the pool identity cached in the plan. Any mismatch means the client's cached pool does not correspond to the on-chain deployment described by the manifest, so execution is refused to prevent swapping on the wrong pool.

Source

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

    plan: &SwapPlan,
    manifest: &BlockchainDeploymentManifest,
) -> anyhow::Result<Address> {
    let matching = manifest
        .pools
        .iter()
        .filter(|pool| Address::from_str(&pool.address).ok() == Some(plan.pool_address))
        .collect::<Vec<_>>();
    anyhow::ensure!(
        matching.len() == 1,
        "Pool {} does not have exactly one deployment manifest definition",
        plan.pool_address
    );
    let pool = matching[0];
    let token0 = Address::from_str(&pool.token0)?;
    let token1 = Address::from_str(&pool.token1)?;
    let factory = Address::from_str(&pool.factory)?;
    let quote_contract = Address::from_str(&pool.quote_contract)?;
    anyhow::ensure!(
        token0 == plan.pool.token0.address
            && token1 == plan.pool.token1.address
            && pool.fee == plan.pool.fee.expect("validated pool fee")
            && factory == plan.factory,
        "Cached pool {} does not match its deployment manifest identity",
        plan.pool_address
    );

    for token in [&plan.pool.token0, &plan.pool.token1] {
        let identities = manifest
            .tokens
            .iter()
            .filter(|identity| Address::from_str(&identity.address).ok() == Some(token.address))
            .collect::<Vec<_>>();
        anyhow::ensure!(
            identities.len() == 1,
            "Token {} does not have exactly one deployment manifest identity",
            token.address

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Invalidate/clear the cached pool and re-resolve it from the current deployment manifest before retrying the swap.
  2. Align the manifest and the cache source to the same environment/chain; regenerate the cache from that manifest.
  3. Fix the mismatched field (token0/token1/fee/factory) in either the manifest or the pool-cache builder so both describe the same pool.
  4. If the pool was redeployed, update the manifest address/fields and rebuild all cached pools referencing the old deployment.

Example fix

// before: cache built from stale environment
let pool = pool_cache.get(plan.pool_address); // fee: 500
// manifest says fee: 3000 for this address -> mismatch
// after: rebuild cache from the active manifest
let pool = resolve_pool_from_manifest(&manifest, plan.pool_address)?;
anyhow::ensure!(pool.fee == manifest_fee, "cache stale; rebuilt from manifest");
Defensive patterns

Strategy: validation

Validate before calling

let m = manifest.pools.iter()
    .find(|p| Address::from_str(&p.address).ok() == Some(pool.address))
    .ok_or("pool missing from manifest")?;
if Address::from_str(&m.token0)? != pool.token0.address
    || Address::from_str(&m.token1)? != pool.token1.address
    || m.fee != pool.fee
    || Address::from_str(&m.factory)? != pool.factory {
    return Err("cached pool identity does not match manifest");
}

Type guard

fn pool_matches_manifest(pool: &CachedPool, m: &ManifestPool) -> anyhow::Result<bool> {
    Ok(Address::from_str(&m.token0)? == pool.token0.address
        && Address::from_str(&m.token1)? == pool.token1.address
        && m.fee == pool.fee
        && Address::from_str(&m.factory)? == pool.factory)
}

Try / catch

match client.execute_swap(plan).await {
    Err(e) if e.to_string().contains("does not match its deployment manifest identity") => {
        // invalidate the pool cache and re-resolve from the manifest
    }
    other => other?,
}

Prevention

When it happens

Trigger: A swap plan is built from a cached pool whose token0.address, token1.address, fee, or factory differs from the manifest entry for the same pool address — a cache populated from a different chain/environment, a stale cache after a pool redeploy, or a fee-tier mismatch.

Common situations: Client restarted with a manifest for a different deployment environment while reusing a persisted cache; a pool was redeployed at the same address after a fork/testnet reset; fee tier changed in config but the cache holds the old fee; copy-pasted token addresses between mainnet and testnet.

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/57e0bbec27f3029b. Report an issue: GitHub.