nautechsystems/nautilus_trader · error
Pool tick spacing must be set
Error message
Pool tick spacing must be set
What it means
PoolProfiler::new() requires the SharedPool to have tick_spacing set, since the profiler's PoolState and tick map construction depend on it. The library panics via expect when pool.tick_spacing is None, i.e. the pool was never initialized with its Uniswap-V3-style tick spacing.
Source
Thrown at crates/model/src/defi/pool_analysis/profiler.rs:108
/// The event timestamp of the last processed event.
pub last_processed_ts: Option<UnixNanos>,
/// Flag indicating whether the pool has been initialized with a starting price.
pub is_initialized: bool,
/// Optional progress reporter for tracking event processing.
reporter: Option<BlockchainSyncReporter>,
/// The last block number that was reported (used for progress tracking).
last_reported_block: u64,
}
impl PoolProfiler {
/// Creates a new [`PoolProfiler`] instance for tracking pool state and events.
///
/// # Panics
///
/// Panics if the pool's tick spacing is not set.
#[must_use]
pub fn new(pool: SharedPool) -> Self {
let tick_spacing = pool.tick_spacing.expect("Pool tick spacing must be set");
let mut state = PoolState::default();
if let Some((fee_protocol0, fee_protocol1)) =
initial_protocol_fee_basis_points(pool.dex.name, pool.fee)
{
state.set_protocol_fee_basis_points(fee_protocol0, fee_protocol1);
}
Self {
pool,
positions: AHashMap::new(),
tick_map: TickMap::new(tick_spacing),
state,
analytics: PoolAnalytics::default(),
last_processed_event: None,
last_processed_ts: None,
is_initialized: false,
reporter: None,View on GitHub (pinned to 18893faf8b)
Solutions
- Populate pool.tick_spacing (e.g. from the factory's tickSpacing() call or the PoolCreated event) before constructing the profiler.
- Guard with if pool.tick_spacing.is_none() { /* fetch topology */ } before calling PoolProfiler::new.
- Reject/fail the pool earlier in ingestion so uninitialized pools never reach the profiler.
Example fix
// before
let profiler = PoolProfiler::new(pool);
// after
assert!(pool.tick_spacing.is_some(), "Pool {} tick spacing missing; fetch topology first", pool.address);
let profiler = PoolProfiler::new(pool); Defensive patterns
Strategy: validation
Validate before calling
if pool.tick_spacing.is_none() { return Err(anyhow::anyhow!("pool tick spacing not set")); } Type guard
fn is_pool_initialized(pool: &SharedPool) -> bool { pool.tick_spacing.is_some() && pool.fee.is_some() } Try / catch
let profiler = if is_pool_initialized(&pool) { Some(PoolProfiler::new(pool)) } else { None }; Prevention
- Fetch tickSpacing during pool topology discovery before any analysis.
- Centralize a completeness check (fee + tick_spacing) for SharedPool construction.
- Reject uninitialized pools at ingestion rather than at use.
When it happens
Trigger: Constructing a PoolProfiler with PoolProfiler::new(pool) where pool.tick_spacing is None — e.g. a SharedPool created from incomplete topology data (factory event without tickSpacing, or a pool stub built before fetching on-chain tick spacing).
Common situations: Running pool analysis on a pool whose topology discovery step failed or was skipped; building SharedPool structs by hand for tests without setting tick_spacing; version changes where tick_spacing became optional.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Pool fee should be initialized
- Latency model should be initialized
- Execution client should be initialized
- Native currency not specified for chain {}
- Must have the `chain` field set
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f9c48c297b1cd7b1.
Report an issue: GitHub.