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
- Verify the symbol passed in is a full OKX option symbol with format UNDERLYING-ASSET-EXPIRY-STRIKE-CP (5 parts).
- Check how the symbol was constructed/cached (instrument_from_cache / parse) to ensure the option expiry component wasn't dropped.
- Log the offending symbol and compare against OKX /api/v5/public/instruments?instType=OPTION output for the correct format.
- 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
- Only pass OKX OPTION instType instruments into option-specific parsing.
- Store the raw exchange symbol verbatim in the instrument cache — never strip segments.
- Add a format unit test pinning the 5-part option symbol shape.
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
- option instruments require instrument_family (OKX instFamily
- option_summary_family_subs mutex poisoned
- Invalid Hyperliquid outcome symbol '{symbol}': encoding must
- Invalid OPRA option symbol: {symbol_str}
- `tick_sz` is empty for {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f16d800fde8731c6.
Report an issue: GitHub.