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

  1. Configure a latency model on the backtest exchange before running the backtest (latency_model field/config)
  2. Ensure the exchange is fully initialized (including latency model) before any commands are processed
  3. Check the exchange construction/builder path for a skipped latency-model assignment
  4. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/f18fe08f5bf7e246. Report an issue: GitHub.