nautechsystems/nautilus_trader · error

Pool profiler for {instrument_id} is not initialized

Error message

Pool profiler for {instrument_id} is not initialized

What it means

Quoting the swap locally requires an initialized pool profiler for the instrument; if the profiler exists but is_initialized is false, prepare_swap aborts. The profiler tracks pool state by replaying pool events, and uninitialized means it has not yet processed enough state to compute a reliable quote.

Source

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

            );
            Some(ceiling)
        } else {
            None
        };

        let profiler = self
            .core
            .cache()
            .pool_profiler(&instrument_id)
            .cloned()
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "No pool profiler for {instrument_id}; an active data subscription is required to quote the swap"
                )
            })?;

        if !profiler.is_initialized {
            anyhow::bail!("Pool profiler for {instrument_id} is not initialized");
        }
        let profiler_position = profiler.last_processed_event.clone().ok_or_else(|| {
            anyhow::anyhow!("Pool profiler for {instrument_id} has processed no events")
        })?;

        let zero_for_one = token_in == pool.token0.address;
        let (amount_in, quoted_amount_out) = match order.order_side() {
            OrderSide::Sell => {
                let quote = profiler
                    .swap_exact_in(base_amount, zero_for_one, None)
                    .map_err(|e| anyhow::anyhow!("Swap quote failed for {instrument_id}: {e}"))?;
                let amount_filled = if zero_for_one {
                    quote.amount0
                } else {
                    quote.amount1
                };

                if amount_filled != I256::from(base_amount) {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Wait for the pool profiler to finish initializing (verify is_initialized / check data-subscription health) before submitting orders.
  2. Add a startup readiness gate that blocks order submission until all required pool profilers report initialized.
  3. Check the data subscription for the pool (RPC/indexer) is active and processing events.

Example fix

// before
client.submit_order(cmd, &order)?; // may hit uninitialized profiler
// after
wait_until(|| client.pool_profiler_initialized(&instrument_id), timeout).await?;
client.submit_order(cmd, &order)?;
Defensive patterns

Strategy: retry

Validate before calling

// Rust
// gate submission on readiness
while !client.pool_profiler_is_initialized(&instrument_id) {
    tokio::time::sleep(Duration::from_millis(500)).await;
}

Try / catch

// Rust
match client.submit_order(cmd, &order) {
    Err(e) if e.to_string().contains("not initialized") => {
        // back off and retry once profiler syncs
        tokio::time::sleep(BACKOFF).await;
    }
    other => other?,
}

Prevention

When it happens

Trigger: submit_order submitted shortly after startup or after subscribing to a new pool, before the pool profiler has finished initializing from historical pool events (profiler.is_initialized == false).

Common situations: Bot restart with an immediate first order before data subscriptions warm up; newly added pool whose historical events are still syncing; data subscription down/slow so the profiler never completes initialization.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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