nautechsystems/nautilus_trader · error · anyhow::Error
Invalid spread symbol format for component: {component}
Error message
Invalid spread symbol format for component: {component} What it means
parse_spread_instrument_id_to_legs decodes a spread instrument ID symbol whose components are encoded leg strings like 'SYMBOL:RATIO'; a component that matches neither the expected leg pattern nor a recognized special case produces this error.
Source
Thrown at crates/adapters/interactive_brokers/src/common/parse.rs:1253
}
}
// Check for positive ratio: (ratio)symbol
if let Some(rest) = component.strip_prefix('(')
&& let Some(pos) = rest.find(')')
{
let ratio_str = &rest[..pos];
let symbol_value = &rest[pos + 1..];
if let Ok(ratio) = ratio_str.parse::<i32>() {
let leg_instrument_id =
InstrumentId::new(NautilusSymbol::from(symbol_value), venue);
result.push((leg_instrument_id, ratio));
continue;
}
}
anyhow::bail!("Invalid spread symbol format for component: {component}");
}
// Sort result alphabetically by symbol
result.sort_by(|a, b| a.0.symbol.as_str().cmp(b.0.symbol.as_str()));
Ok(result)
}
#[cfg(test)]
mod tests {
use ibapi::contracts::{Contract, Currency, Exchange, OptionRight, SecurityType, Symbol};
use nautilus_model::identifiers::InstrumentId;
use rstest::rstest;
use super::{
exchange_to_mic_venue, ib_contract_to_instrument_id_simplified,
instrument_id_to_ib_contract, possible_exchanges_for_venue,
};View on GitHub (pinned to 18893faf8b)
Solutions
- Construct spread instrument IDs with create_spread_instrument_id instead of manual strings
- Check the failing component has the expected 'SYMBOL:RATIO' encoding with an integer ratio
- Log/print the full spread symbol and compare each component against the parser's expected format
- If a legacy format is involved, regenerate the spread ID in the current format
Example fix
// before
let id = InstrumentId::from("AAPL251212C00250000-MSFT.OPT"); // no :ratio
// after
let id = create_spread_instrument_id(&[
(InstrumentId::from("AAPL 251212C00250000.OPRA"), -1),
(InstrumentId::from("AAPL 251212P00250000.OPRA"), 1),
])?; Defensive patterns
Strategy: try-catch
Validate before calling
fn looks_like_leg(c: &str) -> bool {
let mut parts = c.rsplitn(2, ':');
match (parts.next(), parts.next()) {
(Some(ratio), Some(_)) => ratio.parse::<i32>().is_ok(),
_ => false,
}
} Try / catch
match parse_spread_instrument_id_to_legs(&spread_id) {
Ok(legs) => legs,
Err(e) if e.to_string().starts_with("Invalid spread symbol format") => {
tracing::error!("malformed spread symbol {}: {e}", spread_id.symbol);
Vec::new()
}
Err(e) => return Err(e),
} Prevention
- Generate spread symbols only via create_spread_instrument_id
- Keep the 'SYMBOL:RATIO' encoding intact; avoid transforming symbols elsewhere
- Add round-trip tests: create -> parse should always succeed
When it happens
Trigger: Calling parse_spread_instrument_id_to_legs (directly or via fetch_spread_instrument) with a manually constructed or malformed spread symbol, e.g. missing the ':ratio' part, non-numeric ratio, or extra separators.
Common situations: Hand-writing spread symbols instead of using create_spread_instrument_id; symbols mutated/truncated by other tooling; legacy spread symbol formats no longer recognized.
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
- Invalid OPRA option symbol: {symbol_str}
- instrument_ratios list needs to have at least 2 legs
- ratio cannot be zero
- All venues must match. Expected {}, was {}
- Invalid Hyperliquid outcome symbol '{symbol}': encoding must
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/409898f0f971dbbc.
Report an issue: GitHub.