{"record":{"id":"5b36312a60de34b8","repo":"nautechsystems/nautilus_trader","slug":"pool-does-not-have-exactly-one-deployment-manif","errorCode":null,"errorMessage":"Pool {} does not have exactly one deployment manifest definition","messagePattern":"Pool (.+?) does not have exactly one deployment manifest definition","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":4125,"sourceCode":"            );\n            Ok((\n                quote.amount,\n                derive_min_amount_out(base_amount, slippage_bps)?,\n            ))\n        }\n    }\n}\n\nfn validate_manifest_pool(\n    plan: &SwapPlan,\n    manifest: &BlockchainDeploymentManifest,\n) -> anyhow::Result<Address> {\n    let matching = manifest\n        .pools\n        .iter()\n        .filter(|pool| Address::from_str(&pool.address).ok() == Some(plan.pool_address))\n        .collect::<Vec<_>>();\n    anyhow::ensure!(\n        matching.len() == 1,\n        \"Pool {} does not have exactly one deployment manifest definition\",\n        plan.pool_address\n    );\n    let pool = matching[0];\n    let token0 = Address::from_str(&pool.token0)?;\n    let token1 = Address::from_str(&pool.token1)?;\n    let factory = Address::from_str(&pool.factory)?;\n    let quote_contract = Address::from_str(&pool.quote_contract)?;\n    anyhow::ensure!(\n        token0 == plan.pool.token0.address\n            && token1 == plan.pool.token1.address\n            && pool.fee == plan.pool.fee.expect(\"validated pool fee\")\n            && factory == plan.factory,\n        \"Cached pool {} does not match its deployment manifest identity\",\n        plan.pool_address\n    );\n","sourceCodeStart":4107,"sourceCodeEnd":4143,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L4107-L4143","documentation":"`validate_manifest_pool` (crates/adapters/blockchain/src/execution/client.rs:4125) looks up the plan's pool address in the deployment manifest and requires exactly one matching pool entry, since it must resolve unique token0/token1/factory/quote-contract identities for the pool. Zero matches means the pool is not in the manifest; more than one means duplicate or conflicting definitions.","triggerScenarios":"Executing a swap whose plan.pool_address does not appear in the deployment manifest's pools list (0 matches), or the manifest contains the same pool address twice or across multiple environments/chains (>=2 matches).","commonSituations":"Stale or incomplete deployment manifest missing a newly created pool; pool address typo or checksum/case variant handled differently; manifest merged from multiple deployment files duplicating a pool entry; running against a different environment's manifest than the one the pool was deployed in.","solutions":["Add a single definition for the pool (address, token0, token1, fee, factory, quote_contract) to the deployment manifest, or point the client at the manifest that contains it.","Deduplicate the pools list in the manifest so each pool address appears exactly once.","Confirm the pool address in the SwapPlan matches the manifest entry exactly (same address bytes).","Regenerate/redeploy the manifest from source so it is in sync with the deployed pools."],"exampleFix":"// before: duplicate pool entries in the manifest\n\"pools\": [\n  { \"address\": \"0xabc...\", \"fee\": 3000 },\n  { \"address\": \"0xabc...\", \"fee\": 3000 }\n]\n// after: exactly one entry per pool address\n\"pools\": [\n  { \"address\": \"0xabc...\", \"fee\": 3000, \"token0\": \"...\", \"token1\": \"...\", \"factory\": \"...\", \"quoteContract\": \"...\" }\n]","handlingStrategy":"validation","validationCode":"let matches: Vec<_> = manifest.pools.iter()\n    .filter(|p| Address::from_str(&p.address).ok() == Some(plan.pool_address))\n    .collect();\nif matches.len() != 1 { return Err(\"pool must appear exactly once in the manifest\"); }","typeGuard":"fn has_unique_pool(manifest: &BlockchainDeploymentManifest, addr: Address) -> bool {\n    manifest.pools.iter()\n        .filter(|p| Address::from_str(&p.address).ok() == Some(addr))\n        .count() == 1\n}","tryCatchPattern":"match client.execute_swap(plan).await {\n    Err(e) if e.to_string().contains(\"exactly one deployment manifest definition\") => {\n        // reload or repair the manifest, then retry\n    }\n    other => other?,\n}","preventionTips":["Run a startup check that every pool in use appears exactly once in the manifest.","Normalize pool addresses (lowercase) when generating the manifest to avoid duplicate variants.","Version and checksum manifests so clients refuse stale or mixed-environment files.","Deduplicate merged deployment files before shipping them."],"tags":["blockchain","manifest","configuration","pool-registry"],"backgroundTag":"entity-not-found","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}