nautechsystems/nautilus_trader · error
No pool profiler for
Error message
No pool profiler for {instrument_id}; an active data subscription is required to quote the swap What it means
Swaps are quoted using an in-memory pool profiler built from live pool-event data. If the cache holds no profiler for the instrument, there is no active data subscription feeding pool state, and the adapter refuses to quote the swap rather than using stale or missing liquidity data.
Solutions
- Start an active data subscription for the instrument/pool before submitting swap orders
- Verify the instrument_id in the order exactly matches the subscribed instrument (network/address/tick-size)
- Wait for profiler warm-up after connect until pool_profiler appears in the cache
- Check that the data client for this venue/pool is enabled in configuration
Example fix
// before: submitting immediately after connect
await client.connect();
client.submit_order(swap_order);
// after: ensure subscription and profiler exist first
await client.subscribe_pool(instrument_id);
while client.cache().pool_profiler(instrument_id).is_none() { sleep(100ms); }
client.submit_order(swap_order); Defensive patterns
Strategy: validation
Validate before calling
if client.cache().pool_profiler(&instrument_id).is_none() {
return Err(format!("no pool profiler for {instrument_id}; subscribe before trading"));
} Type guard
fn profiler_ready(cache: &Cache, id: &InstrumentId) -> bool {
cache.pool_profiler(id).map(|p| p.is_initialized && p.last_processed_event.is_some()).unwrap_or(false)
} Try / catch
match client.submit_order(order).await {
Err(e) if e.to_string().contains("No pool profiler") => {
client.subscribe_pool(instrument_id).await?;
wait_for_profiler(&instrument_id).await?;
client.submit_order(order).await
}
r => r,
} Prevention
- Subscribe to market data for every DEX instrument before enabling it for orders
- Gate order submission on profiler readiness (exists + initialized + has events)
- Verify instrument_id consistency between trading config and subscriptions
When it happens
Trigger: `submit_order()` -> `prepare_swap()` calls `cache().pool_profiler(&instrument_id)` and gets None because no data subscription for that pool is active.
Common situations: Ordering on a DEX instrument whose market-data stream was never subscribed or was unsubscribed; cache restarted and profiler not yet rebuilt; instrument_id mismatch between the trading config and the subscription.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Pool profiler for has processed no events
- cannot advance an RPC profiler without a snapshot watermark
- Pool profiler for is not initialized
- A recoverable execution for wallet
- Active execution intent
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/05f2b50a283a8cd7.
Report an issue: GitHub.
Appendix: source
Thrown at crates/adapters/blockchain/src/execution/client.rs:1659
anyhow::ensure!(
ceiling.spend_token_decimals == quote_token.decimals,
"Quote spend limit for token {} uses {} decimals, expected pool quote-token decimals {}",
ceiling.spend_token,
ceiling.spend_token_decimals,
quote_token.decimals
);
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 {View on GitHub (pinned to 18893faf8b)