nautechsystems/nautilus_trader · error · anyhow::Error
cancel order failed
Error message
cancel order failed
What it means
Canceling a regular order over the OKX private WebSocket failed. ws_private.cancel_order returned an error, the adapter emitted an order cancel failure event (without an emitter event payload), and the task logs 'cancel order failed' with the underlying cause. Commonly a transport-level WS failure or OKX rejecting the cancel command.
Source
Thrown at crates/adapters/okx/src/execution.rs:993
.cancel_order(
command.trader_id,
command.strategy_id,
command.instrument_id,
Some(command.client_order_id),
command.venue_order_id,
)
.await;
if let Err(e) = result {
emit_cancel_failure(
classify_okx_ws_failure(&e),
None,
command.client_order_id,
command.instrument_id,
command.strategy_id,
command.venue_order_id,
);
return Err(anyhow::Error::new(e).context("cancel order failed"));
}
Ok(())
});
}
fn cancel_order_http(&self, cmd: &CancelOrder) {
self.ensure_order_identity(cmd.client_order_id, cmd.strategy_id, cmd.instrument_id);
let http_client = self.http_client.clone();
let command = cmd.clone();
let emitter = self.emitter.clone();
let clock = self.clock;
self.spawn_task("cancel_order_http", async move {
let result = http_client
.cancel_order(
command.instrument_id,View on GitHub (pinned to 18893faf8b)
Solutions
- Read the chained cause for the OKX WS error; if the order no longer exists (already filled/canceled), treat the cancel as moot and let reconciliation update order state.
- Check ws_private connection health; ensure the adapter was connected and authenticated (valid credentials, correct live/demo flag) before issuing cancels.
- Retry the cancel via HTTP fallback if WS keeps failing, or use cancel_all_orders for bulk cleanup.
- Ensure the cancel targets a live order: verify via the cache/reconciliation that the order is open and the venue_order_id binding is present.
Example fix
// before: canceling without checking order state
trader.cancel_order(client_order_id);
// after: only cancel open orders
if let Some(order) = cache.order(&client_order_id) {
if !order.is_closed() {
trader.cancel_order(client_order_id);
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Only cancel orders that are still open
let open = cache.order(&client_order_id).map(|o| !o.is_closed()).unwrap_or(false);
if !open { return; } Try / catch
// Handle cancel failure without treating it as fatal
if let Err(e) = trader.cancel_order(client_order_id) {
log::warn!("cancel failed: {e:?}");
// rely on reconciliation to confirm final order state
} Prevention
- Check order.is_closed() in the cache before canceling.
- Run reconciliation after restarts so venue bindings exist for cancels.
- Watch WS private connection status before issuing cancels.
- Use HTTP cancel fallback when WS is unstable.
When it happens
Trigger: cancel_order routed to RegularWs; ws_private.cancel_order returned Err: WebSocket disconnected/reconnecting, request timeout awaiting OKX ack, or the client_order_id/venue_order_id no longer matches an open order (already filled or canceled).
Common situations: Canceling an order that was already filled or canceled; WS private connection dropped mid-session; canceling an order submitted in a prior process where no venue_order_id binding exists; OKX rejection codes returned on the WS channel.
Related errors
- submit algo order failed
- batch cancel orders failed
- Binance Futures data teardown failed: {}
- Binance Spot data teardown failed: {}
- WS submit order failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/819fddba16549357.
Report an issue: GitHub.