{"record":{"id":"96ecbe5899524816","repo":"nautechsystems/nautilus_trader","slug":"no-option-expirations-for-currency","errorCode":null,"errorMessage":"No option expirations for {currency}","messagePattern":"No option expirations for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/deribit/src/http/client.rs","lineNumber":1955,"sourceCode":"    /// # Errors\n    ///\n    /// Returns an error if the request fails.\n    pub async fn request_option_expirations(\n        &self,\n        currency: DeribitCurrency,\n    ) -> anyhow::Result<Vec<String>> {\n        let params = GetExpirationsParams::new(currency.as_str(), DeribitExpirationKind::Option);\n        let full_response = self\n            .inner\n            .get_expirations(params)\n            .await\n            .map_err(|e| anyhow::anyhow!(e))?;\n        let response = full_response\n            .result\n            .ok_or_else(|| anyhow::anyhow!(\"No result in expirations response\"))?;\n        let expirations = response\n            .expirations_for_currency(currency.as_str())\n            .ok_or_else(|| anyhow::anyhow!(\"No option expirations for {currency}\"))?;\n\n        Ok(expirations.option.clone())\n    }\n\n    /// Requests position status reports for reconciliation.\n    ///\n    /// Fetches positions from Deribit and converts them to Nautilus [`PositionStatusReport`].\n    ///\n    /// # Strategy\n    /// - Uses `currency=any` to fetch all positions in one call\n    /// - Filters by instrument_id if provided\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the request fails or parsing fails.\n    pub async fn request_position_status_reports(\n        &self,\n        account_id: AccountId,","sourceCodeStart":1937,"sourceCodeEnd":1973,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/deribit/src/http/client.rs#L1937-L1973","documentation":"After fetching expirations, request_option_expirations looks up the per-currency entry via expirations_for_currency and requires its `option` expirations. When the currency key is missing from the response map there is no Option expirations list, so the call fails. This is a lookup miss on a response that did return a result.","triggerScenarios":"Calling request_option_expirations(currency) where the returned expirations map has no entry for that exact currency string (case mismatch or currency not present in the payload).","commonSituations":"Passing a lowercase or non-canonical currency symbol, or a currency that lists expirations only for futures but not options.","solutions":["Use the canonical uppercase Deribit currency code matching the response keys.","Confirm the currency actually lists option instruments; otherwise handle the absence gracefully.","Log available keys from the response to see which currencies were returned."],"exampleFix":"// before\nlet expirations = response\n    .expirations_for_currency(currency.as_str())\n    .ok_or_else(|| anyhow::anyhow!(\"No option expirations for {currency}\"))?;\n// after\nlet expirations = response.expirations_for_currency(currency.as_str()).ok_or_else(|| {\n    anyhow::anyhow!(\n        \"No option expirations for {currency}; available: {:?}\",\n        response.available_currencies()\n    )\n})?;","handlingStrategy":"fallback","validationCode":"// Guard against non-canonical currency strings before the call\nlet currency = currency.to_uppercase();\nassert!(!currency.is_empty());","typeGuard":null,"tryCatchPattern":"match client.request_option_expirations(currency).await {\n    Ok(x) => handle(x),\n    Err(e) if e.to_string().contains(\"No option expirations for\") => Vec::new(), // fall back to empty\n    Err(e) => return Err(e),\n}","preventionTips":["Normalize currency strings (uppercase, no whitespace) before lookup","Treat missing option expirations as an expected empty case for currencies without options","Log available currencies from the response when a lookup misses"],"tags":["api","lookup","empty-response","rust"],"backgroundTag":"record-not-found","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}