{"record":{"id":"d70cbc56c73a1b50","repo":"nautechsystems/nautilus_trader","slug":"pool-venue-chain-blockchain-does-not-match-the-c","errorCode":null,"errorMessage":"Pool venue chain {blockchain} does not match the client chain {chain_name}","messagePattern":"Pool venue chain (.+?) does not match the client chain (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":807,"sourceCode":"\n        Ok(included.tx_hash)\n    }\n\n    fn uniswap_v3_factory(&self) -> anyhow::Result<Address> {\n        crate::exchanges::get_dex_extended(self.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                    self.chain.name\n                )\n            })\n    }\n\n    fn resolve_pool(&self, instrument_id: &InstrumentId) -> anyhow::Result<Pool> {\n        let (blockchain, dex_type) = instrument_id.venue.parse_dex()?;\n        if blockchain != self.chain.name {\n            anyhow::bail!(\n                \"Pool venue chain {blockchain} does not match the client chain {}\",\n                self.chain.name\n            );\n        }\n\n        if dex_type != DexType::UniswapV3 {\n            anyhow::bail!(\"Unsupported DEX type {dex_type}; only UniswapV3 is supported\");\n        }\n\n        let pool_identifier = PoolIdentifier::new_checked(instrument_id.symbol.as_str())?;\n        if !pool_identifier.is_address() {\n            anyhow::bail!(\n                \"Pool identifier {pool_identifier} is a pool ID; only address identifiers are supported\"\n            );\n        }\n\n        let pool = self\n            .core","sourceCodeStart":789,"sourceCodeEnd":825,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L789-L825","documentation":"resolve_pool() parses the instrument ID's venue as a `(blockchain, dex_type)` pair and refuses any instrument whose venue chain differs from the chain this execution client is connected to. Each client instance is bound to exactly one blockchain (`self.chain.name`), so pools on other chains must be routed through that chain's own client. The check runs before any DEX or cache lookup.","triggerScenarios":"Calling `preflight`, `restore_swap_plan`, or `prepare_swap` with an `InstrumentId` whose venue encodes a different blockchain than the client's chain — e.g. passing venue `arbitrum/uniswap_v3` to an Ethereum client, or using a venue string whose chain component is misspelled or renamed so it parses to a different/unknown chain name.","commonSituations":"Routing instruments to the wrong execution client in a multi-chain setup; venue naming drift (config uses `arb` while the registry expects `arbitrum`); building instrument IDs programmatically with a chain variable that points at the wrong network; running against a testnet client while instruments reference mainnet venues.","solutions":["Send the instrument to the execution client constructed for its venue chain (make the client lookup keyed by chain).","Check the instrument ID venue string for typos and correct chain naming (e.g. `ethereum/uniswap_v3:0x...`) so the parsed blockchain matches the client's chain.","If instruments are configured from an external file, validate at startup that every instrument's venue chain matches the client chain it will be assigned to."],"exampleFix":"// before: single client used for all chains\nclient.prepare_swap(instrument_id, ...).await?; // instrument on arbitrum\n\n// after: dispatch by chain\nlet client = clients.get(instrument_id.venue.parse_dex()?.0)\n    .with_context(|| format!(\"no client for {}\", instrument_id.venue))?;\nclient.prepare_swap(instrument_id, ...).await?;","handlingStrategy":"validation","validationCode":"let (blockchain, _dex) = instrument_id.venue.parse_dex()?;\nif blockchain != client.chain.name {\n    anyhow::bail!(\"instrument {} is on {blockchain}, client is on {}\", instrument_id, client.chain.name);\n}\n// safe to call client.prepare_swap(...).await?","typeGuard":"fn belongs_to_chain(instrument_id: &InstrumentId, chain: &str) -> anyhow::Result<bool> {\n    Ok(instrument_id.venue.parse_dex()?.0 == chain)\n}","tryCatchPattern":"match client.prepare_swap(&instrument_id, plan).await {\n    Err(e) if e.to_string().contains(\"does not match the client chain\") => {\n        error!(\"wrong client for instrument; re-route to the {} client\", instrument_id.venue);\n    }\n    other => other?,\n}","preventionTips":["Maintain a map from chain name to its execution client and dispatch instruments by their parsed venue chain.","Validate all configured instruments against their assigned client chain at startup.","Standardize venue naming for chains across configs to avoid parse drift."],"tags":["blockchain","instrument-id","venue-mismatch","multi-chain","configuration"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}