nautechsystems/nautilus_trader · critical · anyhow::Error

WS cancel order failed: {e}

Error message

WS cancel order failed: {e}

What it means

Raised inside the spawned cancel_order_ws task when the Binance WebSocket API cancel_order_with_id call fails. The client removes the cancel's pending request, logs 'WS cancel request failed for {client_order_id}', and bails with this message wrapping the venue error. Because the cancel did not reach the exchange, the order may still be live — treat this as a risk-relevant failure, not a cleanup detail.

Source

Thrown at crates/adapters/binance/src/futures/execution.rs:845

            // Pre-register before sending to avoid response racing the insert
            let request_id = ws_client.next_request_id();
            dispatch_state.pending_requests.insert(
                request_id.clone(),
                PendingRequest {
                    client_order_id,
                    venue_order_id,
                    operation: PendingOperation::Cancel,
                },
            );

            self.spawn_task("cancel_order_ws", async move {
                if let Err(e) = ws_client
                    .cancel_order_with_id(request_id.clone(), params)
                    .await
                {
                    dispatch_state.pending_requests.remove(&request_id);
                    log::error!("WS cancel request failed for {client_order_id}: {e}");
                    anyhow::bail!("WS cancel order failed: {e}");
                }
                Ok(())
            });

            return;
        }

        let http_client = self.http_client.clone();

        self.spawn_task("cancel_order", async move {
            let result = if use_algo_cancel {
                // Try algo cancel first; if it fails, the order may have been triggered
                // before this session started, so fall back to regular cancel
                match http_client.cancel_algo_order(client_order_id).await {
                    Ok(()) => Ok(()),
                    Err(algo_err) => {
                        log::debug!("Algo cancel failed, trying regular cancel: {algo_err}");
                        http_client

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Read the embedded WS error code in the logged {e}: -2011 means the order is already filled/cancelled and the state should be reconciled, not retried
  2. Verify the order is actually open (order status reports) before retrying the cancel
  3. Throttle cancels within venue limits; batch cancel where available
  4. If WS errors persist, check connection health or use the HTTP cancel path if configured
Defensive patterns

Strategy: try-catch

Validate before calling

// Only attempt a cancel when the order is live:
if matches!(order.status(), OrderStatus::Accepted | OrderStatus::Triggered | OrderStatus::PendingUpdate) {
    client.cancel_order(order.clone()).await?;
}

Try / catch

// cancel failures are async: on OrderCanceled absence + 'WS cancel request failed' log,
//   - error -2011 (unknown order): reconcile status, do NOT retry
//   - rate limit / transient: retry once after backoff
//   - still live after retry: escalate (flatten via reduce-only order) per risk policy

Prevention

When it happens

Trigger: Cancelling over the WS order channel with an unknown/already-filled order id (-2011 Unknown order sent), during a WS reconnect window, under cancel-rate limits, or with params rejected by the venue (e.g. cancel-replace race already resolved).

Common situations: Cancel bursts during volatility tripping rate limits; cancels racing order fills; WS session expiry between submit and cancel; reconciliation loops cancelling stale orders that no longer exist.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/ed8d26dd84415098. Report an issue: GitHub.