nautechsystems/nautilus_trader · error
Latency model should be initialized
Error message
Latency model should be initialized
What it means
The backtest exchange stores its latency model in an Option-like holder and unwraps it when computing inflight command latencies. If no latency model was configured on the exchange before processing trading commands, the unwrap site panics with 'Latency model should be initialized'. It is an internal precondition violation: commands are being processed before setup completed.
Source
Thrown at crates/backtest/src/exchange.rs:869
command.ts_init() + latency_model.get_update_latency()
}
TradingCommand::CancelOrder(_)
| TradingCommand::CancelOrders(_)
| TradingCommand::CancelAllOrders(_) => {
command.ts_init() + latency_model.get_delete_latency()
}
_ => panic!("Cannot handle command: {command:?}"),
};
let counter = self
.inflight_counter
.entry(ts)
.and_modify(|e| *e += 1)
.or_insert(1);
(ts, *counter)
} else {
panic!("Latency model should be initialized");
}
}
/// Processes a single order book delta.
///
/// # Errors
///
/// Returns an error if module pre-processing or matching engine processing fails.
pub fn process_order_book_delta(&mut self, delta: OrderBookDelta) -> anyhow::Result<()> {
self.pre_process_modules(&Data::BookDelta(delta))?;
if !self.matching_engines.contains_key(&delta.instrument_id) {
let instrument = {
let cache = self.cache.as_ref().borrow();
cache.instrument(&delta.instrument_id).cloned()
};
if let Some(instrument) = instrument {View on GitHub (pinned to 18893faf8b)
Solutions
- Configure a latency model on the backtest exchange before running the backtest (latency_model field/config)
- Ensure the exchange is fully initialized (including latency model) before any commands are processed
- Check the exchange construction/builder path for a skipped latency-model assignment
- Consider making the latency model a required constructor parameter to move the failure to build time
Example fix
// before let exchange = BacktestExchange::new(...); // latency model never set exchange.process(command); // panics // after let exchange = BacktestExchange::new(...).with_latency_model(LatencyModel::new(...)); exchange.process(command);
Defensive patterns
Strategy: type-guard
Validate before calling
if exchange.latency_model().is_none() {
return Err("backtest exchange requires a latency model before processing commands".into());
} Type guard
fn is_ready(exchange: &BacktestExchange) -> bool {
exchange.latency_model().is_some()
} Prevention
- Always configure a latency model in backtest configs; treat it as mandatory setup
- Make the latency model a required constructor argument so omission fails at build time
- Initialize the exchange fully before feeding it any trading commands
- Add an integration test that runs a minimal backtest to catch setup-order regressions
When it happens
Trigger: Submitting/routing any trading command through the backtest exchange when its latency model was never set (e.g. exchange built without latency config, or command processed before initialization).
Common situations: Backtest config omits latency model parameters; a custom exchange builder skips the latency-model step; ordering bug where commands are processed during setup before initialization finishes.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Cannot handle command: {command:?}
- Execution client should be initialized
- Matching engine not found for instrument {order_instrument_i
- Matching engine not found for instrument {instrument_id}
- Matching engine should be initialized
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f18fe08f5bf7e246.
Report an issue: GitHub.