{"record":{"id":"8edac62a12679bee","repo":"nautechsystems/nautilus_trader","slug":"derive-option-chain-reference-prices-require-an-op","errorCode":null,"errorMessage":"Derive option-chain reference prices require an option instrument (got {instrument_id})","messagePattern":"Derive option-chain reference prices require an option instrument \\(got (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/data.rs","lineNumber":1499,"sourceCode":"                log::error!(\"Failed to send Derive bars response: {e}\");\n            }\n            Ok(())\n        });\n\n        Ok(())\n    }\n\n    fn request_option_chain_reference_price(\n        &self,\n        request: RequestOptionChainReferencePrice,\n    ) -> anyhow::Result<()> {\n        let series_id = request.series_id;\n        let instrument_id = request.instrument_id;\n        let instrument = self\n            .instruments\n            .get_cloned(&instrument_id)\n            .ok_or_else(|| InstrumentLookupError::not_found(instrument_id))?;\n        anyhow::ensure!(\n            matches!(instrument, InstrumentAny::CryptoOption(_)),\n            \"Derive option-chain reference prices require an option instrument (got {instrument_id})\",\n        );\n        let venue_symbol = format_venue_symbol(&instrument_id)?.to_string();\n\n        let http_client = self.http_client.clone();\n        let sender = self.data_sender.clone();\n        let clock = self.clock;\n        let client_id = request.client_id.unwrap_or(self.client_id);\n        let request_id = request.request_id;\n        let params = request.params;\n\n        self.spawn_task(\"request_option_chain_reference_price\", async move {\n            let price = match http_client.get_ticker(&venue_symbol).await {\n                Ok(ticker) => match ticker.option_pricing.as_ref() {\n                    Some(pricing) if pricing.forward_price > Decimal::ZERO => {\n                        match Price::from_decimal(pricing.forward_price) {\n                            Ok(price) => Some(price),","sourceCodeStart":1481,"sourceCodeEnd":1517,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/data.rs#L1481-L1517","documentation":"This error is raised when requesting option-chain reference prices from the Derive adapter with an instrument that is not a Derive crypto option. The client looks the instrument up in its cached instrument map, and `anyhow::ensure!` verifies the cached entry is an `InstrumentAny::CryptoOption` variant; anything else (or a lookup failure, which surfaces separately as InstrumentLookupError) aborts the request. It protects downstream code that only option instruments can satisfy (venue symbol formatting and option-chain subscription semantics).","triggerScenarios":"Calling `request_option_chain_reference_price` (or the subscribe/request path that builds an `OptionChainReferencePriceRequest`) with an instrument_id that resolves to a cached `CryptoPerpetual`, `CryptoFuture`, or other non-option instrument on Derive.","commonSituations":"Configuring an instrument ID that points at a perp or future instead of an option (e.g. `ETH-PERP` rather than an option series); a stale or wrong instrument cached under that ID after a venue relisting; copying an instrument ID from a different venue or product line into an option-chain request.","solutions":["Pass an instrument_id that identifies a Derive crypto option (an option series/instrument, not a perp or future).","Ensure the option instrument was loaded/cached in the client (`self.instruments`) before the request so lookup succeeds and resolves to CryptoOption.","Check the instrument's type at the call site with a matches! guard on InstrumentAny::CryptoOption before issuing the request.","If the ID is generated programmatically, fix the ID construction to use the option instrument's venue symbol."],"exampleFix":"// before\nlet request = OptionChainReferencePriceRequest { instrument_id: \"ETH-PERP.DERIVE\".parse()? };\n\n// after\nlet request = OptionChainReferencePriceRequest { instrument_id: \"ETH-20260925-3000-C.DERIVE\".parse()? };","handlingStrategy":"validation","validationCode":"if let Some(instrument) = client.get_instrument(&instrument_id) {\n    anyhow::ensure!(matches!(instrument, InstrumentAny::CryptoOption(_)),\n        \"{instrument_id} is not a Derive option\");\n    // proceed with request\n}","typeGuard":"fn is_crypto_option(instrument: &InstrumentAny) -> bool {\n    matches!(instrument, InstrumentAny::CryptoOption(_))\n}","tryCatchPattern":null,"preventionTips":["Only issue option-chain reference price requests with option-series instrument IDs","Load instruments into the client cache before requesting","Type-check the cached instrument before calling","Keep perp/future and option request paths separate"],"tags":["derive","instrument","options","rust"],"backgroundTag":"invalid-argument-value","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"}