{"record":{"id":"81876d854a4e4e6b","repo":"nautechsystems/nautilus_trader","slug":"invalid-symbol-format-missing-base-currency-in","errorCode":null,"errorMessage":"Invalid symbol format: missing base currency in '{symbol}'","messagePattern":"Invalid symbol format: missing base currency in '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/common/parse.rs","lineNumber":288,"sourceCode":"                OKXInstrumentType::Events\n            }\n        }\n        _ if dash_count > 4 => OKXInstrumentType::Events,\n        _ => OKXInstrumentType::Spot, // Default fallback\n    }\n}\n\n/// Extracts base and quote currencies from an OKX symbol.\n///\n/// All OKX instrument symbols start with {BASE}-{QUOTE}, regardless of type.\n///\n/// # Errors\n///\n/// Returns an error if the symbol doesn't contain at least two parts separated by '-'.\npub fn parse_base_quote_from_symbol(symbol: &str) -> anyhow::Result<(&str, &str)> {\n    let mut parts = symbol.split('-');\n    let base = parts.next().ok_or_else(|| {\n        anyhow::anyhow!(\"Invalid symbol format: missing base currency in '{symbol}'\")\n    })?;\n    let quote = parts.next().ok_or_else(|| {\n        anyhow::anyhow!(\"Invalid symbol format: missing quote currency in '{symbol}'\")\n    })?;\n    Ok((base, quote))\n}\n\n/// Extracts the instrument family from an OKX symbol string.\n///\n/// All OKX derivative symbols encode the family as the first two segments:\n/// `BTC-USD-250328-92000-C` -> `BTC-USD`, `BTC-USDT-SWAP` -> `BTC-USDT`.\n///\n/// # Errors\n///\n/// Returns an error if the symbol does not contain at least two dash-separated parts.\npub fn extract_inst_family(symbol: &str) -> anyhow::Result<Ustr> {\n    let (base, quote) = parse_base_quote_from_symbol(symbol)?;\n    Ok(Ustr::from(&format!(\"{base}-{quote}\")))","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/common/parse.rs#L270-L306","documentation":"parse_base_quote_from_symbol splits an OKX instrument id like 'BTC-USDT' or 'BTC-USD-240329' on '-' and extracts base and quote. Although split() on a non-empty string always yields a first element, the code guards with ok_or_else; this 'missing base currency' error represents a malformed/empty symbol input where no base part could be extracted.","triggerScenarios":"Called from extract_inst_family, parse_position_status_report, subscribe/unsubscribe_index_prices, or request_index_price with a symbol string that is empty or otherwise yields no base segment before the first '-' (empty string input is the practical trigger).","commonSituations":"Passing an empty instrument id from an uninitialized config or a subscription event with a blank instId; a bug upstream that forwards None-as-empty-string symbols; constructing symbols manually and forgetting the instType/instId convention; OKX payload field renamed so the symbol field read as empty.","solutions":["Validate the instrument id is non-empty and matches the OKX format BASE-QUOTE[-DATE] before calling (regex like ^[A-Za-z0-9]+-[A-Za-z0-9]+(-\\d{6})?$).","Check where the symbol originates — config instrument_ids, subscription messages, or position reports — and fix the empty source value.","Use the instrument id exactly as OKX returns it (e.g. from the instruments endpoint) instead of hand-building the string.","If OKX deserialization yields an empty instId, check the adapter's message schema against the current OKX API docs for renamed fields."],"exampleFix":"// before\nparse_base_quote_from_symbol(&inst_id)?;\n\n// after\nif inst_id.is_empty() || !inst_id.contains('-') {\n    return Err(anyhow::anyhow!(\"invalid OKX instrument id: '{inst_id}'\"));\n}\nparse_base_quote_from_symbol(&inst_id)?;","handlingStrategy":"validation","validationCode":"fn valid_okx_symbol(s: &str) -> bool {\n    !s.is_empty() && s.split('-').next().map(|p| !p.is_empty()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match parse_base_quote_from_symbol(symbol) {\n    Ok((base, quote)) => (base, quote),\n    Err(e) => return Err(anyhow::anyhow!(\"bad instrument id '{symbol}': {e}\")),\n}","preventionTips":["Validate instrument ids against the OKX format at config-load time.","Source instrument ids from the OKX instruments endpoint rather than hand-building them.","Guard against empty strings from uninitialized config or renamed payload fields."],"tags":["rust","okx","symbol-parsing","input-validation"],"backgroundTag":"invalid-identifier-format","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"}