{"record":{"id":"9fb43b0d084fa7c4","repo":"nautechsystems/nautilus_trader","slug":"cannot-subscribe-for-synthetic-instrument-orderbo","errorCode":null,"errorMessage":"Cannot subscribe for synthetic instrument `OrderBookDelta` data","messagePattern":"Cannot subscribe for synthetic instrument `OrderBookDelta` data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/data/src/engine/mod.rs","lineNumber":3115,"sourceCode":"            .iter()\n            .filter(|(_, sid)| **sid == series_id)\n            .map(|(id, _)| *id)\n            .collect();\n\n        for id in &instrument_ids {\n            self.option_chain_instrument_index.remove(id);\n            manager_rc.borrow_mut().handle_instrument_expired(id);\n        }\n\n        manager_rc.borrow_mut().teardown(&self.clock);\n        self.option_chain_managers.remove(&series_id);\n\n        log::info!(\"Proactively torn down expired option chain {series_id}\");\n    }\n\n    fn subscribe_book_deltas(&mut self, cmd: &SubscribeBookDeltas) -> anyhow::Result<bool> {\n        if cmd.instrument_id.is_synthetic() {\n            anyhow::bail!(\"Cannot subscribe for synthetic instrument `OrderBookDelta` data\");\n        }\n\n        // Validate parent shape BEFORE mutating subscription state so a parse\n        // failure leaves the engine bookkeeping unchanged.\n        let parent = resolve_parent_components(&cmd.instrument_id, cmd.params.as_ref())?;\n\n        let had_deltas =\n            self.has_book_delta_subscription_key(cmd.instrument_id, cmd.client_id, cmd.venue);\n\n        if cmd.managed {\n            self.setup_book_updater(&cmd.instrument_id, cmd.book_type, true, parent)?;\n        }\n\n        self.increment_book_delta_subscription(cmd.instrument_id, cmd.client_id, cmd.venue);\n\n        Ok(!had_deltas)\n    }\n","sourceCodeStart":3097,"sourceCodeEnd":3133,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/data/src/engine/mod.rs#L3097-L3133","documentation":"subscribe_book_deltas rejects OrderBookDelta subscriptions for synthetic instrument IDs. Order book deltas come from a venue data client; synthetic instruments are locally computed and have no order book stream, so the subscription is invalid.","triggerScenarios":"Calling DataEngine.subscribe_book_deltas (or subscribe_order_book_deltas) with a cmd.instrument_id where is_synthetic() is true — e.g. an ID from SyntheticInstrument.","commonSituations":"Pointing a book-delta subscription config at a synthetic instrument by mistake; programmatically generating instrument IDs and losing track of which are synthetic; copying subscription setup from a real instrument to a synthetic one.","solutions":["Subscribe to book deltas only for real venue-listed instrument IDs","Check instrument_id.is_synthetic() before issuing the book-delta subscription","If synthetic price streams are needed, use the SyntheticInstrument API / synthetic quote data instead of an order book subscription","Fix config where a synthetic ID string (containing '=' synthetic notation) was pasted as the instrument ID"],"exampleFix":"// before\nengine.subscribe_book_deltas(SubscribeBookDeltas::new(synthetic_id, client_id, venue));\n// after\nanyhow::ensure!(!synthetic_id.is_synthetic(), \"book deltas require a venue instrument\");\nengine.subscribe_book_deltas(SubscribeBookDeltas::new(synthetic_id, client_id, venue));","handlingStrategy":"validation","validationCode":"if instrument_id.is_synthetic() {\n    // no order book stream exists for synthetic instruments\n    return Ok(());\n}","typeGuard":"fn supports_book_data(id: &InstrumentId) -> bool {\n    !id.is_synthetic()\n}","tryCatchPattern":"match engine.subscribe_book_deltas(&cmd) {\n    Err(e) if e.to_string().contains(\"synthetic\") => {\n        log::error!(\"synthetic ID used for book deltas: {e}\");\n    }\n    other => other?,\n}","preventionTips":["Validate instrument IDs at config load: reject synthetic notation for book feeds","Use SyntheticInstrument APIs for computed prices instead of book subscriptions","Distinguish synthetic vs venue instruments in strategy config schemas"],"tags":["rust","data-engine","order-book","synthetic-instrument"],"backgroundTag":"unsupported-operation","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"}