{"record":{"id":"fb01aaf0d3929a59","repo":"nautechsystems/nautilus_trader","slug":"invalid-opra-option-symbol-symbol-str","errorCode":null,"errorMessage":"Invalid OPRA option symbol: {symbol_str}","messagePattern":"Invalid OPRA option symbol: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/common/parse.rs","lineNumber":662,"sourceCode":"    if venue_matches(venue_str.as_str(), VENUES_CRYPTO)\n        && let Some(captures) = parse_crypto_symbol(symbol_str)\n    {\n        return Ok(Contract {\n            contract_id: 0,\n            symbol: Symbol::from(&captures.base),\n            security_type: SecurityType::Crypto,\n            exchange: Exchange::from(exchange_str),\n            currency: Currency::from(&captures.quote),\n            local_symbol: format!(\"{}.{}\", captures.base, captures.quote),\n            ..Default::default()\n        });\n    }\n\n    // Handle Options (OPT)\n    if is_option_venue(venue_str.as_str()) {\n        if venue_str == \"OPRA\" {\n            if !is_canonical_occ_option_symbol(symbol_str) {\n                anyhow::bail!(\"Invalid OPRA option symbol: {symbol_str}\");\n            }\n\n            return Ok(Contract {\n                contract_id: 0,\n                security_type: SecurityType::Option,\n                exchange: Exchange::from(exchange_str),\n                currency: Currency::from(\"USD\"),\n                local_symbol: symbol_str.to_string(),\n                ..Default::default()\n            });\n        }\n\n        if let Some(opt) = parse_option_symbol(symbol_str) {\n            return Ok(Contract {\n                contract_id: 0,\n                symbol: Symbol::from(&opt.symbol),\n                security_type: SecurityType::Option,\n                exchange: Exchange::from(exchange_str),","sourceCodeStart":644,"sourceCodeEnd":680,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/common/parse.rs#L644-L680","documentation":"The Interactive Brokers adapter only accepts canonical OCC option symbols when the instrument venue is OPRA (e.g. AAPL  251212C00250000). This error is raised in instrument_id_to_ib_contract when the symbol fails the is_canonical_occ_option_symbol check, because IB contract construction for options depends on OCC-format fields (underlying, expiry, right, strike).","triggerScenarios":"Calling instrument_id_to_ib_contract with an InstrumentId whose venue is OPRA but whose symbol is not a 21-character canonical OCC symbol (e.g. truncated OCC, named-style symbols like 'AAPL US 12/12/25 C250', or a wrong-length padded symbol).","commonSituations":"Data feeds that emit non-OCRA option IDs, hand-built option InstrumentIds, symbol normalization that strips OCC padding, or tests constructing option IDs with alternative formats.","solutions":["Ensure the option symbol is the full 21-character OCC format (6-char underlying, 6-digit YYMMDD, C/P, 8-digit strike x1000)","Build option InstrumentIds via the adapter's canonical conversion path rather than manual strings","If using a non-OPRA venue, check the exchange mapping / venue so the OPRA branch is not entered","If the symbol is a valid OCC name like a flexible symbol, verify is_canonical_occ_option_symbol semantics before converting"],"exampleFix":"// before\nlet instrument_id = InstrumentId::from(\"AAPL251212C00250000.OPRA\");\n// after (canonical OCC, 21 chars, padded underlying)\nlet instrument_id = InstrumentId::from(\"AAPL  251212C00250000.OPRA\");","handlingStrategy":"validation","validationCode":"fn is_canonical_occ_symbol(s: &str) -> bool {\n    s.len() == 21\n        && s.as_bytes()[6..12].iter().all(u8::is_ascii_digit)\n        && matches!(s.as_bytes()[12], b'C' | b'P')\n        && s.as_bytes()[13..].iter().all(u8::is_ascii_digit)\n}","typeGuard":null,"tryCatchPattern":"match instrument_id_to_ib_contract(&instrument_id) {\n    Ok(contract) => contract,\n    Err(e) if e.to_string().contains(\"Invalid OPRA option symbol\") => {\n        eprintln!(\"symbol {} is not canonical OCC: {e}\", instrument_id.symbol);\n        return;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always use the canonical 21-character OCC format for OPRA option symbols","Build option IDs through the library's conversion helpers, not by hand","Unit-test option symbol parsing with padded underlyings and both C/P rights"],"tags":["rust","options","symbol-parsing","interactive-brokers"],"backgroundTag":"invalid-argument-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"}