nautechsystems/nautilus_trader · error

Pool {instrument_id} references factory {}, expected registe

Error message

Pool {instrument_id} references factory {}, expected registered factory {factory}

What it means

Before executing a swap the client verifies that the pool's DEX factory matches the Uniswap V3 factory registered with the client. If the pool was deployed by a different factory, the swap plan is rejected to avoid interacting with an untrusted pool.

Source

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

                    anyhow::bail!(
                        "BUY quote amount {amount_in} exceeds the configured `quote_spend_limits` maximum {} for {token_in} -> {token_out}",
                        ceiling.max_amount
                    );
                }
                (amount_in, base_amount)
            }
        };
        let min_amount_out = derive_min_amount_out(quoted_amount_out, slippage_bps)?;

        self.ensure_transaction_ready(TransactionPurpose::Swap)?;

        if self.signer.is_none() {
            anyhow::bail!("Signer not initialized; connect the client first");
        }

        let pool_address = pool.address;
        let factory = self.uniswap_v3_factory()?;
        anyhow::ensure!(
            pool.dex.factory == factory,
            "Pool {instrument_id} references factory {}, expected registered factory {factory}",
            pool.dex.factory
        );

        Ok(SwapPlan {
            order: order.clone(),
            pool,
            quote_currency,
            instrument_id,
            pool_address,
            router: self.router_addresses[0],
            factory,
            weth: self.weth_address,
            token_in,
            token_out,
            fee,
            amount_in,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Register the factory that actually deployed the pool, or use a pool from the registered factory's deployment.
  2. Verify the factory address and chain configuration match the pool's network.
  3. Check that pool.dex.factory was populated from the correct on-chain `factory()` call.
  4. Confirm the client is connected to the same chain the pool lives on.

Example fix

// before: pool from a fork factory
// uniswap_v3_factory = 0x1F98431c8aD... (Uniswap)
pool.dex.factory = 0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865; // PancakeSwap
// after: use the matching pool/factory
let factory = self.uniswap_v3_factory()?;
let pool = registry.get_pool_by_factory(factory, ...)?;
Defensive patterns

Strategy: validation

Validate before calling

let factory = client.registered_factory()?;
if pool.dex.factory != factory { return Err("pool factory mismatch"); }

Type guard

fn pool_matches_factory(pool: &Pool, factory: Address) -> bool { pool.dex.factory == factory }

Try / catch

match client.submit_order(order) { Err(e) if e.to_string().contains("expected registered factory") => switch_to_compliant_pool(e), Ok(r) => r }

Prevention

When it happens

Trigger: Calling submit_order -> prepare_swap for a pool whose `pool.dex.factory` differs from the address returned by `self.uniswap_v3_factory()` — e.g. pool created on a fork or different deployment than the configured factory.

Common situations: Configured factory address points at Uniswap V3 while the pool is from PancakeSwap/Sushi or a fork; wrong chain configured so addresses resolve to different deployments; typo in factory registration.

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/be84e3d75b5e73d1. Report an issue: GitHub.