nautechsystems/nautilus_trader · error

Pool venue chain {blockchain} does not match the client chai

Error message

Pool venue chain {blockchain} does not match the client chain {chain_name}

What it means

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.

Source

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

        Ok(included.tx_hash)
    }

    fn uniswap_v3_factory(&self) -> anyhow::Result<Address> {
        crate::exchanges::get_dex_extended(self.chain.name, &DexType::UniswapV3)
            .map(|dex| dex.factory)
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "No registered Uniswap V3 deployment for chain {}",
                    self.chain.name
                )
            })
    }

    fn resolve_pool(&self, instrument_id: &InstrumentId) -> anyhow::Result<Pool> {
        let (blockchain, dex_type) = instrument_id.venue.parse_dex()?;
        if blockchain != self.chain.name {
            anyhow::bail!(
                "Pool venue chain {blockchain} does not match the client chain {}",
                self.chain.name
            );
        }

        if dex_type != DexType::UniswapV3 {
            anyhow::bail!("Unsupported DEX type {dex_type}; only UniswapV3 is supported");
        }

        let pool_identifier = PoolIdentifier::new_checked(instrument_id.symbol.as_str())?;
        if !pool_identifier.is_address() {
            anyhow::bail!(
                "Pool identifier {pool_identifier} is a pool ID; only address identifiers are supported"
            );
        }

        let pool = self
            .core

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Send the instrument to the execution client constructed for its venue chain (make the client lookup keyed by chain).
  2. 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.
  3. 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.

Example fix

// before: single client used for all chains
client.prepare_swap(instrument_id, ...).await?; // instrument on arbitrum

// after: dispatch by chain
let client = clients.get(instrument_id.venue.parse_dex()?.0)
    .with_context(|| format!("no client for {}", instrument_id.venue))?;
client.prepare_swap(instrument_id, ...).await?;
Defensive patterns

Strategy: validation

Validate before calling

let (blockchain, _dex) = instrument_id.venue.parse_dex()?;
if blockchain != client.chain.name {
    anyhow::bail!("instrument {} is on {blockchain}, client is on {}", instrument_id, client.chain.name);
}
// safe to call client.prepare_swap(...).await?

Type guard

fn belongs_to_chain(instrument_id: &InstrumentId, chain: &str) -> anyhow::Result<bool> {
    Ok(instrument_id.venue.parse_dex()?.0 == chain)
}

Try / catch

match client.prepare_swap(&instrument_id, plan).await {
    Err(e) if e.to_string().contains("does not match the client chain") => {
        error!("wrong client for instrument; re-route to the {} client", instrument_id.venue);
    }
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/d70cbc56c73a1b50. Report an issue: GitHub.