nautechsystems/nautilus_trader · error

Pool identifier {pool_identifier} is a pool ID; only address

Error message

Pool identifier {pool_identifier} is a pool ID; only address identifiers are supported

What it means

resolve_pool() requires the instrument ID's symbol to be a pool contract address (checked via `PoolIdentifier::is_address()`), not a symbolic pool ID. This adapter identifies on-chain pools directly by their deployed contract address so it can bind to the exact Uniswap V3 pool, rather than resolving human-readable pool IDs. A non-address symbol bails before the cache lookup.

Source

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

            })
    }

    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
            .cache()
            .pool(instrument_id)
            .cloned()
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "Unknown pool {instrument_id}; not found in the shared engine cache"
                )
            })?;

        if pool.token0.get_token_priority() == pool.token1.get_token_priority() {
            anyhow::bail!(
                "Pool {instrument_id} tokens share a token priority; base and quote orientation is ambiguous"

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Replace the symbol with the pool's contract address, e.g. `ethereum/uniswap_v3:0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`.
  2. If you only know the pair, derive the pool address from the Uniswap V3 factory (`getPool(tokenA, tokenB, fee)`) or a deployment registry at configuration time and use that address.
  3. Add a startup validation step that asserts every swap instrument's symbol is a hex address, failing fast before any swap is attempted.

Example fix

// before
let id = InstrumentId::from("ethereum/uniswap_v3:ETH-USDC");
client.preflight(&id, ...).await?;

// after
let id = InstrumentId::from("ethereum/uniswap_v3:0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640");
client.preflight(&id, ...).await?;
Defensive patterns

Strategy: validation

Validate before calling

let symbol = instrument_id.symbol.as_str();
let is_addr = symbol.starts_with("0x")
    && symbol.len() == 42
    && Address::parse_checksummed(symbol, None).is_ok();
if !is_addr {
    anyhow::bail!("symbol '{symbol}' is not a pool address; resolve the V3 pool address first");
}
// safe to call client.prepare_swap(...).await?

Type guard

fn symbol_is_pool_address(instrument_id: &InstrumentId) -> bool {
    let s = instrument_id.symbol.as_str();
    s.starts_with("0x") && s.len() == 42 && Address::parse_checksummed(s, None).is_ok()
}

Try / catch

match client.preflight(&instrument_id, quote, slippage).await {
    Err(e) if e.to_string().contains("only address identifiers are supported") => {
        error!("use a 0x pool address symbol, not a symbolic pool ID: {}", instrument_id);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `preflight`, `restore_swap_plan`, or `prepare_swap` with an `InstrumentId` whose symbol is a pool ID string (e.g. `ETH-USDC` or a Nautilus-generated pool identifier) instead of a 0x-prefixed 20-byte hex address. The venue must be correct (chain and UniswapV3 pass earlier checks) for this error to be reached.

Common situations: Constructing instrument IDs from data catalogs or strategy configs that use symbolic identifiers (e.g. `ethereum/uniswap_v3:ETH-USDC`); copying instruments from docs/examples that use symbolic names; a fixture or registry that produced pool-ID style symbols; forgetting to map a human-readable pair name to its V3 pool address at config time.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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