nautechsystems/nautilus_trader · error
Cancel order failed: {e}
Error message
Cancel order failed: {e} What it means
The cancel_order command runs in a spawned task; if the ws_client cancel-order request to Deribit fails, the error is logged with order_id and client_order_id and re-raised as 'Cancel order failed: {e}'. Like modify_order, cancel_order returns Ok(()) immediately; the failure is observable only in the spawned task's error path.
Source
Thrown at crates/adapters/deribit/src/execution.rs:973
log::debug!("Canceling order: order_id={order_id}, client_order_id={client_order_id}");
// Spawn async task to send cancel via WebSocket
self.spawn_task("cancel_order", async move {
if let Err(e) = ws_client
.cancel_order(
&order_id,
client_order_id,
trader_id,
strategy_id,
instrument_id,
)
.await
{
log::error!(
"Cancel order failed: order_id={order_id}, client_order_id={client_order_id}, error={e}"
);
anyhow::bail!("Cancel order failed: {e}");
}
Ok(())
});
Ok(())
}
fn cancel_all_orders(&self, cmd: CancelAllOrders) -> anyhow::Result<()> {
let instrument_id = cmd.instrument_id;
// Without a side filter, use efficient bulk cancel via Deribit API
let Some(order_side) = cmd.order_side else {
log::debug!(
"Cancelling all orders: instrument={instrument_id}, order_side=None (bulk)"
);
let ws_client = self.ws_client.clone();
self.spawn_task("cancel_all_orders", async move {View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the logged inner error for the venue rejection reason (e.g. unknown order vs connection failure)
- Verify the order is still open before cancelling; treat 'already filled/cancelled' rejections as benign
- Check WebSocket connectivity and re-authenticate if the session dropped
- Retry the cancel once connectivity is restored, or use cancel_all_orders as a safety net
Example fix
// before
if let Err(e) = ws_client.cancel_order(order_id, client_order_id).await {
anyhow::bail!("Cancel order failed: {e}");
}
// after
if let Err(e) = ws_client.cancel_order(order_id, client_order_id).await {
if !e.to_string().contains("not found") && !e.to_string().contains("already") {
anyhow::bail!("Cancel order failed: {e}");
}
log::info!("order already inactive on venue: {order_id}");
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before cancelling, confirm the order is still live
if !open_orders.contains(&venue_order_id) {
log::info!("skip cancel: order not open");
return Ok(());
} Try / catch
match client.cancel_order(cmd).await {
Ok(()) => {}, // failure surfaces asynchronously in the spawned task
Err(e) => log::error!("cancel dispatch failed: {e}"),
}
// on 'Cancel order failed' in task logs, treat already-filled/cancelled as benign Prevention
- Maintain accurate local open-order state to avoid cancelling dead orders
- Deduplicate cancel requests for the same order_id
- Monitor spawned-task logs for the venue rejection reason
- Use cancel_all_orders as a periodic safety net during disconnects
When it happens
Trigger: Calling cancel_order for an order_id/client_order_id unknown to Deribit, an already-filled or cancelled order, or when the request fails due to auth, rate limits, or a dropped WebSocket connection.
Common situations: Cancelling an order that was just filled (common race in fast markets); duplicate cancel attempts; stale order IDs after reconnect; WebSocket disconnection mid-request.
Related errors
- Modify order failed: {e}
- Cancel all orders failed: {e}
- InstrumentState channel requires kind and currency parameter
- errors joined with "; " (aggregated disconnect errors)
- errors joined with "; " (aggregated disconnect errors)
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/622c7e1ba9f57bed.
Report an issue: GitHub.