{"record":{"id":"9f5fd436fc855431","repo":"nautechsystems/nautilus_trader","slug":"no-matching-engine-found-for-instrument","errorCode":null,"errorMessage":"No matching engine found for instrument {}","messagePattern":"No matching engine found for instrument (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/exchange.rs","lineNumber":890,"sourceCode":"\n    /// Processes a single order book delta.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if module pre-processing or matching engine processing fails.\n    pub fn process_order_book_delta(&mut self, delta: OrderBookDelta) -> anyhow::Result<()> {\n        self.pre_process_modules(&Data::BookDelta(delta))?;\n\n        if !self.matching_engines.contains_key(&delta.instrument_id) {\n            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    ///","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/exchange.rs#L872-L908","documentation":"The backtest exchange processes a data delta whose instrument is not present in the cache, so it cannot create (or find) a matching engine for that instrument. The exchange lazily adds a matching engine only when the instrument for the data's instrument_id exists in the cache; when cache.instrument() returns None it fails with this error. It prevents book/quote/trade data for unknown instruments from silently being dropped.","triggerScenarios":"Calling SimulatedExchange process functions such as process_order_book_delta (exchange.rs:890) with an OrderBookDelta whose instrument_id was never added via add_instrument, and no instrument with that ID exists in the provided cache.","commonSituations":"Replaying recorded data where the instrument definitions file was not loaded first; instrument_id venue/symbol casing mismatch between data and instrument definitions; loading data for a venue that was not registered in the backtest config; renamed or delisted instruments in historical datasets.","solutions":["Load instrument definitions into the cache before feeding data (e.g. pass instruments via the BacktestEngine config add_instrument or ensure the data catalog/instrument provider loads them).","Verify the instrument_id in the delta exactly matches a cached instrument (venue and symbol, case-sensitive).","Log the missing instrument_id and compare against cache.instrument_ids() to find the mismatch.","If the data legitimately has no instrument definition, filter those deltas out before passing them to the exchange."],"exampleFix":"// before\nexchange.process_order_book_delta(&delta)?; // delta for BTCUSDT.BINANCE, instrument never added\n\n// after\nengine.add_instrument(test_instrument_btcusdt_binance()); // or configure instrument provider\nexchange.process_order_book_delta(&delta)?;","handlingStrategy":"validation","validationCode":"fn ensure_instrument_cached(cache: &Cache, instrument_id: &InstrumentId) -> anyhow::Result<()> {\n    if cache.instrument(instrument_id).is_none() {\n        anyhow::bail!(\"Instrument {instrument_id} not in cache; load definitions before feeding data\");\n    }\n    Ok(())\n}","typeGuard":"let Some(instrument) = cache.instrument(&delta.instrument_id) else {\n    anyhow::bail!(\"Skipping delta for unknown instrument {}\", delta.instrument_id);\n};","tryCatchPattern":"match exchange.process_order_book_delta(&delta) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"No matching engine found\") => {\n        log::warn!(\"skipping unregistered instrument delta: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always load the full instrument catalog before streaming market data into the backtest.","Preflight-compare the set of instrument_ids in your data files against cache.instrument_ids().","Use a single instrument provider configuration so data venue suffixes and definitions stay in sync."],"tags":["backtest","matching-engine","instrument-not-found","rust"],"backgroundTag":"resource-not-found","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"}