{"record":{"id":"cfcb747ed4c9f44c","repo":"nautechsystems/nautilus_trader","slug":"batch-cancel-orders-failed","errorCode":null,"errorMessage":"batch cancel orders failed","messagePattern":"batch cancel orders failed","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/execution.rs","lineNumber":2593,"sourceCode":"                drop(cache);\n\n                log::debug!(\n                    \"Canceling {} regular orders and {} algo orders for {}\",\n                    regular_payload.len(),\n                    algo_orders.len(),\n                    cmd.instrument_id\n                );\n\n                if !regular_payload.is_empty() {\n                    let ws_private = self.ws_private.clone();\n\n                    self.spawn_task(\"batch_cancel_orders\", async move {\n                        if let Err(e) = ws_private.batch_cancel_orders(regular_payload).await {\n                            log_batch_cancel_failure(\n                                classify_okx_ws_failure(&e),\n                                regular_cancel_contexts.len(),\n                            );\n                            return Err(anyhow::Error::new(e).context(\"batch cancel orders failed\"));\n                        }\n                        Ok(())\n                    });\n                }\n\n                // OKX doesn't support algo cancel via private WebSocket, must use HTTP\n                if !algo_orders.is_empty() {\n                    let items: Vec<_> = algo_orders\n                        .into_iter()\n                        .map(\n                            |(\n                                instrument_id,\n                                client_order_id,\n                                venue_order_id,\n                                _trader_id,\n                                strategy_id,\n                            )| {\n                                let request = OKXCancelAlgoOrderRequest {","sourceCodeStart":2575,"sourceCodeEnd":2611,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/execution.rs#L2575-L2611","documentation":"The OKX execution client spawns an async task to cancel open orders in bulk over the OKX private WebSocket. When `ws_private.batch_cancel_orders` returns an error (transport failure, auth issue, or venue rejection), the task wraps it with anyhow context \"batch cancel orders failed\". This is used by cancel_all_orders, so it means some or all pending cancel requests may not have reached OKX.","triggerScenarios":"Calling cancel_all_orders on the OKX execution client while the private WebSocket is disconnected, reconnecting, or when OKX rejects the batch cancel request payload (e.g. sCode errors in the response for one or more orders).","commonSituations":"Network flaps or WebSocket drop right before canceling all orders during an emergency flatten; OKX session expired / re-login in progress; exceeding OKX batch cancel size limits; canceling orders that were already filled or canceled, causing per-order rejection in the batch response.","solutions":["Check the OKX adapter logs for the classified failure (log_batch_cancel_failure output) to see if it is transport, auth, or venue rejection.","Verify the private WebSocket is connected and authenticated before issuing cancels; reconnect and retry.","Retry the batch cancel (cancels are idempotent; already-canceled orders report as such).","Fall back to individual order cancels or the HTTP cancel path for orders that failed in the batch.","Confirm order count is within OKX batch size limits for batch cancel."],"exampleFix":"// before\nlet result = client.cancel_all_orders(&instrument_id, OrderSide::Both);\n// after\nmatch client.cancel_all_orders(&instrument_id, OrderSide::Both) {\n    Ok(()) => {}\n    Err(e) => {\n        tracing::error!(\"batch cancel failed: {e}; retrying after reconnect\");\n        ws.reconnect().await;\n        client.cancel_all_orders(&instrument_id, OrderSide::Both)?;\n    }\n}","handlingStrategy":"retry","validationCode":"// before canceling\nassert!(ws_private.is_connected(), \"OKX private WS must be connected\");\nassert!(!orders.is_empty() && orders.len() <= 20, \"within OKX batch limit\");","typeGuard":null,"tryCatchPattern":"match result {\n    Ok(()) => {}\n    Err(e) if is_transport_failure(&e) => {\n        backoff_retry(|| client.cancel_all_orders(&instrument_id, side)).await?;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Monitor WS connection state and only cancel when authenticated/connected","Keep order state cached so already-closed orders are excluded from batches","Retry cancels idempotently with backoff","Log classify_okx_ws_failure categories to detect recurring transport issues"],"tags":["okx","websocket","cancel-orders","network"],"backgroundTag":"api-request-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}