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
- Load/subscribe the spread instrument on the adapter before expecting spread order updates
- Verify the sprd_id string matches the cached key exactly (OKX spread IDs like 'BTC-USDT_BTC-USDT-250328')
- On unknown sprd_id, fetch the spread definition via OKX HTTP API and insert into the instruments cache, then re-parse
- 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
- Explicitly load every spread instrument the strategy trades before enabling the spread orders stream
- Keep sprd_id strings exactly as OKX reports them
- Persist/restore spread instrument cache across adapter restarts
- Reconcile open spread orders at startup to backfill missing definitions
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
- No instrument found for inst_id: {}
- Unsupported algo order type: {:?}
- Missing sz for algo order {}
- Cannot determine spread fill quantity: fill_sz='{}' and acc_
- missing fee for spread fill report sprd_id={}; OKX sprd-orde
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e5c6219d18ecfa1c.
Report an issue: GitHub.