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.addressView on GitHub (pinned to 18893faf8b)
Solutions
- Invalidate/clear the cached pool and re-resolve it from the current deployment manifest before retrying the swap.
- Align the manifest and the cache source to the same environment/chain; regenerate the cache from that manifest.
- Fix the mismatched field (token0/token1/fee/factory) in either the manifest or the pool-cache builder so both describe the same pool.
- 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
- Rebuild the pool cache whenever the manifest version/checksum changes.
- Key caches by (chain_id, pool_address) so cross-environment reuse cannot happen.
- Compare fee and factory — not just addresses — whenever a pool is loaded from cache.
- Clear persisted caches after testnet resets or pool redeploys.
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
- Allowed token pair {token_in} -> {token_out} is not fully pi
- Persisted swap trader does not match restored order
- Pool {} does not have exactly one deployment manifest defini
- Wallet token {address} does not have exactly one deployment
- Deployment manifest has no capability probe target
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/57e0bbec27f3029b.
Report an issue: GitHub.