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

  1. 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.
  2. Check ws_private connection health; ensure the adapter was connected and authenticated (valid credentials, correct live/demo flag) before issuing cancels.
  3. Retry the cancel via HTTP fallback if WS keeps failing, or use cancel_all_orders for bulk cleanup.
  4. 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

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


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