{"record":{"id":"425bc7ce66857c64","repo":"nautechsystems/nautilus_trader","slug":"matching-engine-should-be-initialized","errorCode":null,"errorMessage":"Matching engine should be initialized","messagePattern":"Matching engine should be initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/exchange.rs","lineNumber":900,"sourceCode":"            let instrument = {\n                let cache = self.cache.as_ref().borrow();\n                cache.instrument(&delta.instrument_id).cloned()\n            };\n\n            if let Some(instrument) = instrument {\n                self.add_instrument(instrument)?;\n            } else {\n                anyhow::bail!(\n                    \"No matching engine found for instrument {}\",\n                    delta.instrument_id\n                );\n            }\n        }\n\n        if let Some(matching_engine) = self.matching_engines.get_mut(&delta.instrument_id) {\n            matching_engine.process_order_book_delta(&delta)?;\n        } else {\n            anyhow::bail!(\"Matching engine should be initialized\");\n        }\n        Ok(())\n    }\n\n    /// Processes a batch of order book deltas.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if module pre-processing or matching engine processing fails.\n    pub fn process_order_book_deltas(&mut self, deltas: &OrderBookDeltas) -> anyhow::Result<()> {\n        self.pre_process_modules(&Data::BookDeltas(Box::new(deltas.clone())))?;\n\n        if !self.matching_engines.contains_key(&deltas.instrument_id) {\n            let instrument = {\n                let cache = self.cache.as_ref().borrow();\n                cache.instrument(&deltas.instrument_id).cloned()\n            };\n","sourceCodeStart":882,"sourceCodeEnd":918,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/exchange.rs#L882-L918","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before\ncache.add_instrument(&instrument); // engine map not populated\nexchange.process_order_book_delta(&delta)?; // Matching engine should be initialized\n\n// after\nengine.add_instrument(instrument.clone()); // goes through add_instrument -> matching_engines.insert\nexchange.process_order_book_delta(&delta)?;","handlingStrategy":"validation","validationCode":"if !exchange.matching_engines().contains_key(&delta.instrument_id) {\n    anyhow::bail!(\"Matching engine not initialized for {}\", delta.instrument_id);\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = exchange.process_order_book_delta(&delta) {\n    if e.to_string().contains(\"should be initialized\") {\n        log::error!(\"Exchange setup incomplete: {e}\");\n        return Err(e);\n    }\n    return Err(e);\n}","preventionTips":["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."],"tags":["backtest","matching-engine","initialization","rust"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}