nautechsystems/nautilus_trader · error · anyhow::Error

Invalid OPRA option symbol: {symbol_str}

Error message

Invalid OPRA option symbol: {symbol_str}

What it means

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).

Source

Thrown at crates/adapters/interactive_brokers/src/common/parse.rs:662

    if venue_matches(venue_str.as_str(), VENUES_CRYPTO)
        && let Some(captures) = parse_crypto_symbol(symbol_str)
    {
        return Ok(Contract {
            contract_id: 0,
            symbol: Symbol::from(&captures.base),
            security_type: SecurityType::Crypto,
            exchange: Exchange::from(exchange_str),
            currency: Currency::from(&captures.quote),
            local_symbol: format!("{}.{}", captures.base, captures.quote),
            ..Default::default()
        });
    }

    // Handle Options (OPT)
    if is_option_venue(venue_str.as_str()) {
        if venue_str == "OPRA" {
            if !is_canonical_occ_option_symbol(symbol_str) {
                anyhow::bail!("Invalid OPRA option symbol: {symbol_str}");
            }

            return Ok(Contract {
                contract_id: 0,
                security_type: SecurityType::Option,
                exchange: Exchange::from(exchange_str),
                currency: Currency::from("USD"),
                local_symbol: symbol_str.to_string(),
                ..Default::default()
            });
        }

        if let Some(opt) = parse_option_symbol(symbol_str) {
            return Ok(Contract {
                contract_id: 0,
                symbol: Symbol::from(&opt.symbol),
                security_type: SecurityType::Option,
                exchange: Exchange::from(exchange_str),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the option symbol is the full 21-character OCC format (6-char underlying, 6-digit YYMMDD, C/P, 8-digit strike x1000)
  2. Build option InstrumentIds via the adapter's canonical conversion path rather than manual strings
  3. If using a non-OPRA venue, check the exchange mapping / venue so the OPRA branch is not entered
  4. If the symbol is a valid OCC name like a flexible symbol, verify is_canonical_occ_option_symbol semantics before converting

Example fix

// before
let instrument_id = InstrumentId::from("AAPL251212C00250000.OPRA");
// after (canonical OCC, 21 chars, padded underlying)
let instrument_id = InstrumentId::from("AAPL  251212C00250000.OPRA");
Defensive patterns

Strategy: validation

Validate before calling

fn is_canonical_occ_symbol(s: &str) -> bool {
    s.len() == 21
        && s.as_bytes()[6..12].iter().all(u8::is_ascii_digit)
        && matches!(s.as_bytes()[12], b'C' | b'P')
        && s.as_bytes()[13..].iter().all(u8::is_ascii_digit)
}

Try / catch

match instrument_id_to_ib_contract(&instrument_id) {
    Ok(contract) => contract,
    Err(e) if e.to_string().contains("Invalid OPRA option symbol") => {
        eprintln!("symbol {} is not canonical OCC: {e}", instrument_id.symbol);
        return;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/fb01aaf0d3929a59. Report an issue: GitHub.