nautechsystems/nautilus_trader · error · anyhow::Error

No instrument found for sprd_id: {}

Error message

No instrument found for sprd_id: {}

What it means

parse_spread_order_msg resolves an OKX spread order message's sprd_id against the local instrument cache; an unknown sprd_id means the spread's legs/definition were never loaded, so no ExecutionReport can be built and this error is thrown. Spread instruments must be explicitly loaded before spread order stream messages are parsed.

Source

Thrown at crates/adapters/okx/src/websocket/parse.rs:1423

    }
}

/// Parses a single OKX spread order message into an [`ExecutionReport`].
///
/// # Errors
///
/// Returns an error if the instrument cannot be found or if parsing the
/// underlying order payload fails.
pub fn parse_spread_order_msg(
    msg: &OKXSpreadOrder,
    account_id: AccountId,
    instruments: &AHashMap<Ustr, InstrumentAny>,
    filled_qty_cache: &AHashMap<Ustr, Quantity>,
    ts_init: UnixNanos,
) -> anyhow::Result<ExecutionReport> {
    let instrument = instruments
        .get(&msg.sprd_id)
        .ok_or_else(|| anyhow::anyhow!("No instrument found for sprd_id: {}", msg.sprd_id))?;
    let previous_filled_qty = filled_qty_cache.get(&msg.ord_id).copied();
    let has_new_fill = (!msg.fill_sz.is_empty() && msg.fill_sz != "0")
        || !msg.trade_id.is_empty()
        || has_acc_fill_sz_increased_value(
            Some(msg.acc_fill_sz.as_str()),
            previous_filled_qty,
            instrument.size_precision(),
        );

    match msg.state {
        OKXOrderStatus::Filled | OKXOrderStatus::PartiallyFilled if has_new_fill => {
            match parse_spread_order_fill_report(
                msg,
                instrument,
                account_id,
                previous_filled_qty,
                ts_init,
            )? {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Load/subscribe the spread instrument on the adapter before expecting spread order updates
  2. Verify the sprd_id string matches the cached key exactly (OKX spread IDs like 'BTC-USDT_BTC-USDT-250328')
  3. On unknown sprd_id, fetch the spread definition via OKX HTTP API and insert into the instruments cache, then re-parse
  4. Skip and log unknown-spread order messages instead of failing the dispatch loop

Example fix

// before
let instrument = instruments
    .get(&msg.sprd_id)
    .ok_or_else(|| anyhow::anyhow!("No instrument found for sprd_id: {}", msg.sprd_id))?;
// after
let instrument = match instruments.get(&msg.sprd_id) {
    Some(inst) => inst,
    None => {
        log::warn("Skipping spread order for unknown sprd_id {sprd_id}; load the spread first");
        return Ok(None);
    }
};
Defensive patterns

Strategy: validation

Validate before calling

// Rust, before parsing spread order updates
if !instruments.contains_key(&msg.sprd_id) {
    log::warn("Spread {sprd_id} not cached; loading spread definition first");
    load_spread_instrument(msg.sprd_id)?;
}

Type guard

fn spread_cached(map: &AHashMap<Ustr, InstrumentAny>, sprd_id: &Ustr) -> bool {
    map.contains_key(sprd_id)
}

Try / catch

match parse_spread_order_msg(&msg, &instruments, account_id, &filled_qty_cache, ts_init) {
    Ok(report) => dispatch(report),
    Err(e) if e.to_string().starts_with("No instrument found for sprd_id") => {
        log::warn("{e}; subscribe/load the spread before expecting its order updates");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A private spread 'orders' ('sprd-orders') WebSocket message arrives whose sprd_id is not present in the instruments AHashMap — the spread was not subscribed/loaded on this adapter session.

Common situations: Spread orders placed via OKX web UI for spreads the adapter never instantiated; sprd_id string mismatch vs cached key; adapter restart losing cached spread instruments while live spread orders stream updates.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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