nautechsystems/nautilus_trader · error · anyhow::Error

Order not found

Error message

Order not found

What it means

request_order_status_report queried GET /api/v1/order with a filter on the order ID and got an empty response, so no order matched and there is nothing to convert into an OrderStatusReport. The adapter treats a missing order as a hard error for status reconciliation.

Source

Thrown at crates/adapters/bitmex/src/http/client.rs:2098

        if let Some(venue_order_id) = venue_order_id {
            params.filter(serde_json::json!({
                "orderID": venue_order_id.as_str()
            }));
        } else if let Some(client_order_id) = client_order_id {
            params.filter(serde_json::json!({
                "clOrdID": client_order_id.as_str()
            }));
        }

        params.count(1i32);
        let params = params.build().map_err(|e| anyhow::anyhow!(e))?;

        let response = self.inner.get_orders(params).await?;

        let order = response
            .into_iter()
            .next()
            .ok_or_else(|| anyhow::anyhow!("Order not found"))?;

        let instrument = self.instrument_from_cache(instrument_id.symbol.inner())?;
        let ts_init = self.generate_ts_init();

        parse_order_status_report(&order, &instrument, &self.order_type_cache, ts_init)
    }

    /// Request multiple order status reports.
    ///
    /// # Errors
    ///
    /// Returns an error if:
    /// - Credentials are missing.
    /// - The request fails.
    /// - The API returns an error.
    pub async fn request_order_status_reports(
        &self,
        instrument_id: Option<InstrumentId>,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Widen the query window by adding a startTime filter, or query without count restrictions, if the order may have aged out.
  2. Confirm the clOrdID exists on the venue via the BitMEX web UI or a direct REST query before treating it as missing.
  3. Check API key/environment (testnet vs production) matches where the order was placed.
  4. For reconciliation flows, treat not-found as a distinct condition (mark unknown/needs review) rather than retrying the identical query.

Example fix

// before
let order = response.into_iter().next().ok_or_else(|| anyhow::anyhow!("Order not found"))?;
// after
let order = response.into_iter().next().ok_or_else(|| anyhow::anyhow!(
    "Order not found for client_order_id={client_order_id:?} on BitMEX (wrong env, aged out, or never accepted)"
))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm the order was accepted at submit time and record the venue's echoed clOrdID
let submit_report = client.submit_order(...).await?;
assert_eq!(submit_report.cl_ord_id, expected_cl_ord_id);

Type guard

fn order_maybe_missing(e: &anyhow::Error) -> bool {
    e.to_string().contains("Order not found")
}

Try / catch

match client.request_order_status_report(instrument_id, Some(cl_id)).await {
    Ok(report) => Ok(Some(report)),
    Err(e) if order_maybe_missing(&e) => Ok(None), // reconcile as unknown, don't crash
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Requesting the status of an order that never reached the venue (submit rejected), was already filled/cancelled and aged out of the default lookback window, uses a clOrdID from another environment, or where the API key lacks visibility (different account).

Common situations: Reconciliation after a restart querying orders older than BitMEX's default query window; testnet/mainnet key mismatch; querying an order placed before a counter reset so clOrdID collides/does not exist; the order still in-flight (submission latency) when queried immediately after submit.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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