nautechsystems/nautilus_trader · error · anyhow::Error
No order returned in cancel response
Error message
No order returned in cancel response
What it means
cancel_order requested a cancel via BitMEX DELETE /api/v1/order but the API returned an empty array of orders, so there is nothing to parse into an OrderStatusReport. The adapter treats an empty cancel response as an error because a successful cancel echoes back the cancelled order.
Source
Thrown at crates/adapters/bitmex/src/http/client.rs:1821
) -> anyhow::Result<OrderStatusReport> {
let mut params = super::query::DeleteOrderParamsBuilder::default();
params.text(NAUTILUS_TRADER);
if let Some(venue_order_id) = venue_order_id {
params.order_id(vec![venue_order_id.as_str().to_string()]);
} else if let Some(client_order_id) = client_order_id {
params.cl_ord_id(vec![client_order_id.as_str().to_string()]);
} else {
anyhow::bail!("Either client_order_id or venue_order_id must be provided");
}
let params = params.build().map_err(|e| anyhow::anyhow!(e))?;
let orders: Vec<BitmexOrder> = self.inner.cancel_orders_response(params).await?;
let order = orders
.into_iter()
.next()
.ok_or_else(|| anyhow::anyhow!("No order returned in cancel response"))?;
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)
}
/// Cancel multiple orders.
///
/// # Errors
///
/// Returns an error if:
/// - Credentials are missing.
/// - The request fails.
/// - The order doesn't exist.
/// - The API returns an error.
pub async fn cancel_orders(
&self,View on GitHub (pinned to 18893faf8b)
Solutions
- Check the order exists and is open (e.g. via query_order/request_order_status_report) before cancelling, or treat empty cancel responses as already-cancelled.
- Verify the client_order_id/venue_order_id corresponds to a live order on the same environment (testnet vs mainnet) and API key.
- If a cancel retry produced this, treat it as success-if-cancelled: look the order up and confirm Canceled status instead of failing.
- Log the exact order id used and confirm with a direct GET /api/v1/order filter query.
Example fix
// before
let order = orders.into_iter().next().ok_or_else(|| anyhow::anyhow!("No order returned in cancel response"))?;
// after
let order = match orders.into_iter().next() {
Some(o) => o,
None => anyhow::bail!(
"Cancel returned no order for client_order_id={client_order_id:?} venue_order_id={venue_order_id:?} (already cancelled/filled or not found)"
),
}; Defensive patterns
Strategy: try-catch
Validate before calling
let open = client.query_order(instrument_id, Some(cl_id), None).await?;
if open.is_none() {
// order already gone; skip cancel
} Type guard
fn first_order(orders: Vec<BitmexOrder>) -> Result<BitmexOrder, String> {
orders.into_iter().next().ok_or_else(|| "empty cancel response".to_string())
} Try / catch
match client.cancel_order(instrument_id, Some(cl_id), None).await {
Ok(report) => handle(report),
Err(e) if e.to_string().contains("No order returned") => {
// treat as already-cancelled: confirm via query_order before alerting
}
Err(e) => return Err(e),
} Prevention
- Check order state via query_order before cancelling to skip already-closed orders.
- Make cancel retries idempotent: an empty cancel response usually means the order is already gone.
- Verify API key environment (testnet vs mainnet) and account match the orders being cancelled.
When it happens
Trigger: Calling cancel_order with a client_order_id or venue_order_id that does not exist on BitMEX, that was already cancelled/filled, or that belongs to a different account/symbol; the order being cancelled concurrently by another process between check and cancel.
Common situations: Re-submitting a cancel after a timeout (idempotency retry on an already-cancelled order); stale VenueOrderId after a disconnect; cancelling during settlement or when the order was rejected on the venue; testnet vs mainnet credential mismatch so the order is not visible to the API key.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Order not found
- No margin data returned from BitMEX
- Failed to create HTTP client {i}: {e}
- Failed to create HTTP client {i}: {e}
- Order {client_order_id} not found
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/5a375159f73eccef.
Report an issue: GitHub.