nautechsystems/nautilus_trader · error

Order detail instrument mismatch for {instrument_id}: return

Error message

Order detail instrument mismatch for {instrument_id}: returned {}

What it means

When a single order-detail record comes back, the adapter verifies that the returned instId matches the instrument_id the caller requested. A mismatch means OKX returned an order for a different instrument than asked — the identifier resolved to a different market — so the adapter bails rather than produce a wrong report.

Source

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

        let params = params_builder
            .build()
            .map_err(|e| anyhow::anyhow!("Failed to build order detail params: {e}"))?;
        let orders = match self.inner.get_order(params).await {
            Ok(orders) => orders,
            Err(e) if e.is_order_not_found() => return Ok(None),
            Err(e) => return Err(e.into()),
        };
        let order = match orders.as_slice() {
            [] => return Ok(None),
            [order] => order,
            _ => anyhow::bail!(
                "Order detail returned {} records for one identifier",
                orders.len(),
            ),
        };

        if order.inst_id.as_str() != instrument_id.symbol.inner() {
            anyhow::bail!(
                "Order detail instrument mismatch for {instrument_id}: returned {}",
                order.inst_id,
            );
        }

        if let Some(venue_order_id) = venue_order_id
            && order.ord_id.as_str() != venue_order_id.as_str()
        {
            anyhow::bail!(
                "Order detail venue order ID mismatch for {venue_order_id}: returned {}",
                order.ord_id,
            );
        }

        let ts_init = self.generate_ts_init();
        let mut report = parse_order_status_report(
            order,
            account_id,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the instrument_id matches the instrument the order was placed on
  2. Use unique client_order_ids per instrument (or query by venue_order_id) to avoid cross-instrument resolution
  3. Check the symbol mapping between Nautilus and OKX (instId formatting) for the instrument

Example fix

// before
client.request_order_detail(wrong_instrument_id, None, Some(venue_order_id)).await?;
// after
client.request_order_detail(order.instrument_id, None, Some(venue_order_id)).await?;
Defensive patterns

Strategy: validation

Validate before calling

// ensure the instrument matches the one the order was placed on
if order.instrument_id != instrument_id {
    return Err(anyhow::anyhow!("instrument mismatch before detail request"));
}

Type guard

fn matches_instrument(report_inst: &str, requested: &InstrumentId) -> bool {
    report_inst == requested.symbol.inner()
}

Try / catch

match client.request_order_detail(instrument_id, coid, void).await {
    Ok(r) => { /* use */ }
    Err(e) if e.to_string().contains("instrument mismatch") => {
        log::error!("wrong instrument for order lookup: {e}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: request_order_detail called with instrument_id X but OKX returns an order whose inst_id differs (e.g. querying a clOrdId that was reused on another instrument, or a stale/incorrect instrument_id).

Common situations: Client order IDs generated without instrument scoping and reused across instruments; cached instrument_id diverging from where the order actually lives; symbol mapping errors between Nautilus InstrumentId and OKX instId.

Related errors


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