nautechsystems/nautilus_trader · critical
Matching engine not found for instrument {instrument_id}
Error message
Matching engine not found for instrument {instrument_id} What it means
When processing a trading command (submit/modify/cancel/cancel-all) the exchange looked up the `MatchingEngine` for the command's instrument ID and, finding none, panicked. The engine map must contain an entry for every instrument whose orders are routed to this venue.
Source
Thrown at crates/backtest/src/exchange.rs:1922
TradingCommand::ModifyOrder(ref command) => {
matching_engine.process_modify(command, account_id);
}
TradingCommand::ModifyOrders(ref command) => {
matching_engine.process_batch_modify(command, account_id);
}
TradingCommand::CancelOrder(ref command) => {
matching_engine.process_cancel(command, account_id);
}
TradingCommand::CancelOrders(ref command) => {
matching_engine.process_batch_cancel(command, account_id);
}
TradingCommand::CancelAllOrders(ref command) => {
matching_engine.process_cancel_all(command, account_id);
}
_ => {}
}
} else {
panic!("Matching engine not found for instrument {instrument_id}");
}
}
fn process_modify_submitted_order(&self, command: &ModifyOrder) -> bool {
let Some(order) = self
.cache
.borrow()
.order(&command.client_order_id)
.map(|o| o.clone())
else {
return false;
};
let modifies_submitted_order = matches!(order.status(), OrderStatus::Submitted)
|| (matches!(order.status(), OrderStatus::PendingUpdate)
&& order
.previous_status()
.is_some_and(|status| matches!(status, OrderStatus::Submitted)));View on GitHub (pinned to 18893faf8b)
Solutions
- Register the instrument (matching engine) with the venue before routing commands to it.
- Filter or gate commands so only instruments registered with this exchange are routed to it.
- Log/instrument-coverage-check which instrument IDs the strategy uses versus venue-registered instruments.
Example fix
// before
engine.cancel_all_orders(instrument_id); // instrument never registered
// after
engine.add_venue(SimulatedExchangeConfig {
instruments: vec![instrument],
..Default::default()
});
engine.cancel_all_orders(instrument_id); Defensive patterns
Strategy: validation
Validate before calling
// before routing commands
if !venue.instrument_ids().contains(&instrument_id) {
eprintln!("skipping command for unregistered instrument {instrument_id}");
return;
} Prevention
- Route commands only to venues that registered the instrument
- Avoid broadcasting cancel-all across venues with disjoint instrument sets
- Verify venue/instrument IDs match after any instrument definition change
When it happens
Trigger: `TradingCommand::CancelAllOrders` (or any single-instrument trading command) targeting an `instrument_id` with no registered matching engine in `exchange.matching_engines`.
Common situations: Cancelling orders on an instrument that was never registered with the venue; commands broadcast to all instruments where some instruments lack engines; data/config mismatch after changing instrument definitions (e.g. different venue or expiration).
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Matching engine not found for instrument {order_instrument_i
- Cannot handle command: {command:?}
- Latency model should be initialized
- Execution client should be initialized
- Position id should be generated. Hedging Oms type order matc
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a1c37c3f9f360a34.
Report an issue: GitHub.