nautechsystems/nautilus_trader · error
Matching engine should be initialized
Error message
Matching engine should be initialized
What it means
The instrument for the delta was found (or already added), but no matching engine is registered in the exchange's matching_engines map for that instrument_id, so the delta cannot be routed. In practice this means the instrument exists in the cache but the exchange never built a matching engine for it — an internal wiring/initialization gap between add_instrument and the engines map.
Source
Thrown at crates/backtest/src/exchange.rs:900
let instrument = {
let cache = self.cache.as_ref().borrow();
cache.instrument(&delta.instrument_id).cloned()
};
if let Some(instrument) = instrument {
self.add_instrument(instrument)?;
} else {
anyhow::bail!(
"No matching engine found for instrument {}",
delta.instrument_id
);
}
}
if let Some(matching_engine) = self.matching_engines.get_mut(&delta.instrument_id) {
matching_engine.process_order_book_delta(&delta)?;
} else {
anyhow::bail!("Matching engine should be initialized");
}
Ok(())
}
/// Processes a batch of order book deltas.
///
/// # Errors
///
/// Returns an error if module pre-processing or matching engine processing fails.
pub fn process_order_book_deltas(&mut self, deltas: &OrderBookDeltas) -> anyhow::Result<()> {
self.pre_process_modules(&Data::BookDeltas(Box::new(deltas.clone())))?;
if !self.matching_engines.contains_key(&deltas.instrument_id) {
let instrument = {
let cache = self.cache.as_ref().borrow();
cache.instrument(&deltas.instrument_id).cloned()
};
View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure instruments are registered through SimulatedExchange::new/add_instrument so a matching engine is created per instrument.
- Check that the exchange was configured with the correct book type, OMS type, and fee model matching the instrument's venue.
- Inspect self.matching_engines keys after setup and confirm the target instrument_id is present before feeding data.
- Recreate the exchange via the standard BacktestEngine add_instrument flow rather than mutating the cache directly.
Example fix
// before cache.add_instrument(&instrument); // engine map not populated exchange.process_order_book_delta(&delta)?; // Matching engine should be initialized // after engine.add_instrument(instrument.clone()); // goes through add_instrument -> matching_engines.insert exchange.process_order_book_delta(&delta)?;
Defensive patterns
Strategy: validation
Validate before calling
if !exchange.matching_engines().contains_key(&delta.instrument_id) {
anyhow::bail!("Matching engine not initialized for {}", delta.instrument_id);
} Try / catch
if let Err(e) = exchange.process_order_book_delta(&delta) {
if e.to_string().contains("should be initialized") {
log::error!("Exchange setup incomplete: {e}");
return Err(e);
}
return Err(e);
} Prevention
- Only register instruments through the exchange/backtest engine API, never by mutating the cache directly.
- After setup, assert every instrument you plan to stream has a matching engine.
- Treat add_instrument errors as fatal instead of continuing with a partially initialized exchange.
When it happens
Trigger: Calling process_order_book_delta (exchange.rs:900) for an instrument that add_instrument accepted but for which no entry exists in self.matching_engines — e.g. the instrument was added to the cache without going through the exchange's engine-construction path.
Common situations: Adding instruments directly to the cache instead of via the exchange; a partially constructed exchange reused after a failed prior setup; custom exchange code that bypasses add_instrument; replaying data for an instrument type not supported by any configured matching engine (e.g. no book type/OMS configured for that venue).
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Latency model should be initialized
- Execution client should be initialized
- Matching engine not found for instrument {order_instrument_i
- Matching engine not found for instrument {instrument_id}
- No matching engine found for instrument {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/425bc7ce66857c64.
Report an issue: GitHub.