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
- Replace the symbol with the pool's contract address, e.g. `ethereum/uniswap_v3:0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`.
- 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.
- 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
- Resolve pair names to Uniswap V3 pool addresses (factory getPool) at config load time and store only address-based instrument IDs.
- Add a startup check that every swap instrument symbol parses as a checksummed hex address.
- Avoid copying symbolic IDs (ETH-USDC style) from catalogs or examples into venue strings for this adapter.
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
- Unsupported DEX type {dex_type}; only UniswapV3 is supported
- Finalized transaction {} emitted {} Swap logs; expected exac
- Invalid venue {}, expected Blockchain DEX format
- Missing tickLower in topic2 when parsing burn event
- Missing tickUpper in topic3 when parsing burn event
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/758faaf34a44fe3b.
Report an issue: GitHub.