nautechsystems/nautilus_trader · error

Expected OKX option symbol with expiry, received {symbol}

Error message

Expected OKX option symbol with expiry, received {symbol}

What it means

This anyhow::ensure! check validates that an OKX option instrument symbol contains at least 5 dash-separated components (e.g. BTC-USD-250926-60000-C), because the function extracts the expiry date from the third component (parts[2]). If the symbol has fewer segments it cannot contain an expiry, so the library rejects it rather than returning a bogus expiry string.

Source

Thrown at crates/adapters/okx/src/http/client.rs:2842

    ) -> anyhow::Result<OKXPriceLimit> {
        let mut params = GetPriceLimitParamsBuilder::default();
        params.inst_id(instrument_id.symbol.inner());
        let params = params.build().map_err(|e| anyhow::anyhow!(e))?;

        let resp = self
            .inner
            .get_price_limit(params)
            .await
            .map_err(|e| anyhow::anyhow!(e))?;

        resp.first()
            .cloned()
            .ok_or_else(|| anyhow::anyhow!("No price limit returned from OKX"))
    }

    fn option_summary_exp_time(symbol: &str) -> anyhow::Result<Option<String>> {
        let parts: Vec<&str> = symbol.split('-').collect();
        anyhow::ensure!(
            parts.len() >= 5,
            "Expected OKX option symbol with expiry, received {symbol}"
        );
        Ok(Some(parts[2].to_string()))
    }

    /// Requests the latest index price for the `instrument_id` from OKX.
    ///
    /// # Errors
    ///
    /// Returns an error if the HTTP request fails or no index price is returned.
    pub async fn request_index_price(
        &self,
        instrument_id: InstrumentId,
    ) -> anyhow::Result<IndexPriceUpdate> {
        // Index tickers endpoint requires base pair format (e.g., BTC-USDT)
        let symbol = instrument_id.symbol.inner();
        let (base, quote) = parse_base_quote_from_symbol(symbol.as_str())?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the symbol passed in is a full OKX option symbol with format UNDERLYING-ASSET-EXPIRY-STRIKE-CP (5 parts).
  2. Check how the symbol was constructed/cached (instrument_from_cache / parse) to ensure the option expiry component wasn't dropped.
  3. Log the offending symbol and compare against OKX /api/v5/public/instruments?instType=OPTION output for the correct format.
  4. If you intentionally handle non-option instruments, route them away from option-specific parsing paths.

Example fix

// before
let expiry = option_summary_exp_time("BTC-USDT")?; // panics into ensure error
// after
let expiry = match option_summary_exp_time("BTC-USD-250926-60000-C") {
    Ok(e) => e,
    Err(err) => { eprintln!("skip non-option symbol: {err}"); return Ok(None); }
};
Defensive patterns

Strategy: validation

Validate before calling

fn is_okx_option_symbol(symbol: &str) -> bool {
    let parts: Vec<&str> = symbol.split('-').collect();
    parts.len() >= 5
}
if !is_okx_option_symbol(&symbol) { return Ok(None); }

Type guard

fn as_option_symbol(symbol: &str) -> Option<(&str, &str, &str, &str, &str)> {
    let p: Vec<&str> = symbol.split('-').collect();
    if p.len() < 5 { return None; }
    Some((p[0], p[1], p[2], p[3], p[4]))
}

Try / catch

match option_summary_exp_time(&symbol) {
    Ok(exp) => use(exp),
    Err(e) => { log::warn!("non-option symbol skipped: {e}"); continue; }
}

Prevention

When it happens

Trigger: Calling option_summary_exp_time with a symbol like "BTC-USDT" or "BTC-USD" (spot/perp style or truncated option symbol) that has fewer than 5 '-' separated parts, e.g. when the instrument cache holds a mis-parsed option symbol.

Common situations: Requesting an OKX option instrument/price-limit whose cached symbol was built incorrectly, using a spot or perpetual symbol where an option symbol is expected, or OKX changing/abbreviating symbol formats in a response that gets fed back into this parser.

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/f16d800fde8731c6. Report an issue: GitHub.