{"record":{"id":"02eba1978751a6a5","repo":"nautechsystems/nautilus_trader","slug":"deployment-manifest-router-set-does-not-match-rou","errorCode":null,"errorMessage":"Deployment manifest router set does not match `router_addresses`","messagePattern":"Deployment manifest router set does not match `router_addresses`","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":394,"sourceCode":"                .iter()\n                .filter(|contract| contract.role == role)\n                .map(|contract| {\n                    Address::from_str(&contract.address)\n                        .map_err(|_| anyhow::anyhow!(\"Deployment manifest address is invalid\"))\n                })\n                .collect::<anyhow::Result<HashSet<_>>>()\n        };\n        let singleton = |role, description: &str| {\n            let addresses = role_addresses(role)?;\n            anyhow::ensure!(\n                addresses.len() == 1,\n                \"Deployment manifest must contain exactly one {description} contract\"\n            );\n            Ok(*addresses.iter().next().expect(\"singleton role address\"))\n        };\n\n        let configured_routers = routers.iter().copied().collect::<HashSet<_>>();\n        anyhow::ensure!(\n            role_addresses(BlockchainContractRole::Router)? == configured_routers,\n            \"Deployment manifest router set does not match `router_addresses`\"\n        );\n        anyhow::ensure!(\n            singleton(BlockchainContractRole::WrappedNative, \"wrapped native\")? == weth,\n            \"Deployment manifest wrapped native contract does not match `weth_address`\"\n        );\n        let factory = singleton(BlockchainContractRole::Factory, \"factory\")?;\n        let registered_factory =\n            crate::exchanges::get_dex_extended(config.chain.name, &DexType::UniswapV3)\n                .map(|dex| dex.factory)\n                .ok_or_else(|| {\n                    anyhow::anyhow!(\n                        \"No registered Uniswap V3 deployment for chain {}\",\n                        config.chain.name\n                    )\n                })?;\n        anyhow::ensure!(","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L376-L412","documentation":"After collecting all `Router`-role addresses from the deployment manifest, `validate_manifest_contracts` compares that set against the router addresses configured in the client config (`router_addresses`). `anyhow::ensure!` fails when the two `HashSet`s differ — meaning the manifest and the explicit config disagree on which router contracts to use.","triggerScenarios":"Initializing the execution client when `manifest.contracts` with role `Router` yields a different address set than the `routers` argument passed to `validate_manifest_contracts` (extra routers in one side, missing in the other, or a different address entirely).","commonSituations":"Updating `router_addresses` in config after a router upgrade without regenerating the manifest; pointing config at a different deployment than the manifest file; adding an additional router to config but not the manifest; checksummed vs lowercase rendering of the same address producing unequal `Address` values is not possible here (parsed to `Address`), so mismatches are genuinely different sets.","solutions":["Make the `Router` entries in the deployment manifest exactly match the `router_addresses` set in the client config","Regenerate the deployment manifest from the same deployment that produced the configured router addresses","If the router list changed intentionally, update both config and manifest together"],"exampleFix":"// before (config) — manifest has only router A\nrouter_addresses: [routerA, routerB]\n// after\nrouter_addresses: [routerA]  // or add routerB to the manifest","handlingStrategy":"validation","validationCode":"let manifest_routers: HashSet<Address> = manifest.contracts.iter()\n    .filter(|c| c.role == BlockchainContractRole::Router)\n    .filter_map(|c| Address::from_str(&c.address).ok())\n    .collect();\nlet configured: HashSet<Address> = config.router_addresses.iter().copied().collect();\nassert_eq!(manifest_routers, configured, \"router set mismatch between manifest and config\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive router_addresses in config from the same manifest file rather than maintaining both by hand","Diff manifest vs config contract sets in CI","Update both sources atomically when routers change"],"tags":["rust","config","ethereum","consistency"],"backgroundTag":"invalid-config-value","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"}