nautechsystems/nautilus_trader · error
Pool profiler for has processed no events
Error message
Pool profiler for {instrument_id} has processed no events What it means
Even when a pool profiler exists, it must have processed at least one pool event (`last_processed_event` set) to quote reliably. An initialized flag without any processed events yields no usable cursor/liquidity state, so the swap is rejected.
Solutions
- Wait until the profiler has processed its first event (poll `last_processed_event`) before submitting swaps
- Check the pool event stream/WebSocket for stalls and reconnect if no events arrive
- Re-trigger history/backfill replay so the profiler ingests past events
- Verify the pool actually emits events (active pool) and the subscription filter targets it
Example fix
// before submit_order(order); // profiler just created // after let profiler = cache.pool_profiler(&id).unwrap(); assert!(profiler.last_processed_event.is_some(), "await first pool event"); submit_order(order);
Defensive patterns
Strategy: validation
Validate before calling
if let Some(p) = client.cache().pool_profiler(&instrument_id) {
if p.last_processed_event.is_none() {
return Err("profiler has no processed events; wait for first pool event".into());
}
} Type guard
fn has_processed_events(p: &PoolProfiler) -> bool {
p.last_processed_event.is_some()
} Try / catch
match client.submit_order(order).await {
Err(e) if e.to_string().contains("has processed no events") => {
wait_until(|| profiler(&instrument_id).last_processed_event.is_some()).await?;
client.submit_order(order).await
}
r => r,
} Prevention
- Wait for at least one processed pool event after subscribing before quoting
- Monitor event-stream liveness and alert when a profiler goes idle
- Ensure backfill/history replay completes before enabling live trading
When it happens
Trigger: `prepare_swap()` finds a profiler with `is_initialized == true` but `last_processed_event == None` — the profiler was created but no pool events were processed before the quote attempt.
Common situations: Submitting orders immediately after subscription before the first event arrives; event stream stalled (RPC/websocket drop) after profiler creation; profiler snapshot restored but history replay not yet started.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- No pool profiler for
- 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/08fc50b9872a9678.
Report an issue: GitHub.
Appendix: source
Thrown at crates/adapters/blockchain/src/execution/client.rs:1668
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) {
anyhow::bail!(
"Local quote for {instrument_id} filled {amount_filled} of the {base_amount} order amount; pool liquidity cannot fill the order"
);View on GitHub (pinned to 18893faf8b)