nautechsystems/nautilus_trader · error
matching engine raw ID exhausted at u32::MAX
Error message
matching engine raw ID exhausted at u32::MAX
What it means
The backtest exchange assigns each newly added instrument a monotonically increasing u32 raw ID for its matching engine. When the internal counter has already reached u32::MAX, checked_add(1) overflows and this error is thrown instead of silently wrapping. It indicates the simulation has tried to register more instruments than can be addressed with a u32 identifier.
Source
Thrown at crates/backtest/src/exchange.rs:488
.bar_adaptive_high_low_ordering(self.bar_adaptive_high_low_ordering)
.trade_execution(self.trade_execution)
.liquidity_consumption(self.liquidity_consumption)
.reject_stop_orders(self.reject_stop_orders)
.support_gtd_orders(self.support_gtd_orders)
.support_contingent_orders(self.support_contingent_orders)
.use_position_ids(self.use_position_ids)
.use_random_ids(self.use_random_ids)
.use_reduce_only(self.use_reduce_only)
.use_market_order_acks(self.use_market_order_acks)
.queue_position(self.queue_position)
.oto_full_trigger(self.oto_full_trigger)
.maybe_price_protection_points(price_protection)
.build();
let instrument_id = instrument.id();
let raw_id = self
.last_raw_id
.checked_add(1)
.ok_or_else(|| anyhow::anyhow!("matching engine raw ID exhausted at u32::MAX"))?;
self.last_raw_id = raw_id;
let mut matching_engine = OrderMatchingEngine::new(
instrument.clone(),
raw_id,
self.fill_model.clone(),
self.fee_model.clone(),
self.book_type,
self.oms_type,
self.account_type,
self.clock.clone(),
Rc::clone(&self.cache),
matching_engine_config,
);
if let Some(handler) = &self.event_handler {
matching_engine.set_event_handler(Rc::clone(handler));
}
self.instruments.insert(instrument_id, instrument);View on GitHub (pinned to 18893faf8b)
Solutions
- Reduce the number of instruments registered in a single backtest run
- Reuse existing instruments instead of re-adding them on every delta/tick
- Create a fresh backtest exchange (resetting last_raw_id) for each run or chunk instead of reusing one across runs
- If genuinely more than u32::MAX instruments are needed, this is unsupported; partition the workload across multiple exchange instances
Example fix
// before: re-adding the instrument on every delta
for delta in deltas { exchange.process_order_book_delta(delta)?; } // re-adds per symbol each time
// after: add once, then only process deltas
for instrument in instruments { exchange.add_instrument(instrument)?; }
for delta in deltas { exchange.process_order_book_delta(delta)?; } Defensive patterns
Strategy: validation
Validate before calling
// before adding instruments, ensure the run stays far below u32::MAX assert!(instruments.len() < u32::MAX as usize, "too many instruments for one exchange"); // and add each instrument only once let added: HashSet<InstrumentId> = HashSet::new();
Prevention
- Add each instrument exactly once, before the data loop
- Create a new exchange per backtest run instead of reusing one across replays
- Watch for code paths that re-register instruments on every delta/tick
When it happens
Trigger: Calling add_instrument (directly or via process_order_book_delta(s), process_order_book_depth10, process_quote_tick, process_trade_tick, or process_bar) after the exchange has already registered 4,294,967,295 instruments in a single run.
Common situations: Extremely long-running or replayed backtests that re-add instruments without resetting the exchange; a bug feeding the same deltas through process_order_book_delta repeatedly, each call registering a new instrument; synthetic data generators producing unbounded instrument IDs.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Time event accumulator sequence overflow
- WETH balance overflow for included transaction {tx_hash} at
- Cannot handle command: {command:?}
- Latency model should be initialized
- Execution client should be initialized
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/951bdefed3ae2a48.
Report an issue: GitHub.