{"record":{"id":"da73737aa5ebfbbe","repo":"nautechsystems/nautilus_trader","slug":"handler-command-channel-closed-e","errorCode":null,"errorMessage":"handler command channel closed: {e}","messagePattern":"handler command channel closed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/adapters/kraken/src/websocket/dispatch/spot_orders.rs","lineNumber":268,"sourceCode":"    ) -> anyhow::Result<u64> {\n        let req_id = self.next_req_id();\n        envelope.req_id = Some(req_id);\n        identity.ts_sent_ns = ts_now_ns;\n\n        let payload = SecretString::from(\n            serde_json::to_string(&envelope)\n                .map_err(|e| anyhow::anyhow!(\"serialize WS order request: {e}\"))?,\n        );\n\n        let cmd_tx = self\n            .cmd_tx()\n            .ok_or_else(|| anyhow::anyhow!(\"WS handler command sender unavailable\"))?;\n\n        self.pending.insert(req_id, identity);\n\n        if let Err(e) = cmd_tx.send(SpotHandlerCommand::SendOrderRequest { req_id, payload }) {\n            self.pending.remove(&req_id);\n            anyhow::bail!(\"handler command channel closed: {e}\");\n        }\n\n        let state_for_timeout = Arc::downgrade(self);\n        let task_spawner = self.task_spawner.read().clone();\n        let cancel = task_spawner.cancellation_token();\n        let timeout = self.timeout;\n\n        if let Err(e) = task_spawner.spawn(async move {\n            tokio::select! {\n                biased;\n                () = cancel.cancelled() => {\n                    if let Some(state) = state_for_timeout.upgrade() {\n                        state.pending.remove(&req_id);\n                    }\n                }\n                () = tokio::time::sleep(timeout) => {\n                    let Some(state) = state_for_timeout.upgrade() else {\n                        return;","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/kraken/src/websocket/dispatch/spot_orders.rs#L250-L286","documentation":"When submitting a Kraken Spot order over WebSocket, the request is dispatched to the handler task through an mpsc command channel. If that channel's receiver has been dropped (the handler task has shut down), the send fails; the adapter removes the pending-request entry it just registered and surfaces the channel error.","triggerScenarios":"Calling send on the Kraken Spot order dispatch after the WS handler task has terminated — e.g. the connection was dropped/disconnected and the handler loop exited, but the dispatch handle is still being used to place an order.","commonSituations":"Ordering during a WebSocket disconnect or reconnect window; network outage killing the handler task while strategy keeps trading; shutting down the adapter while in-flight logic still attempts submissions.","solutions":["Check WS connection state and reconnect before retrying the order submission.","Implement an on-disconnect callback/hook that pauses order flow until the handler task is live again.","Retry the order through a freshly (re)connected Kraken Spot WS client.","Log and alert on this error — it usually indicates the adapter's background task died and needs supervision."],"exampleFix":"// before\nclient.send_order(payload)?; // may fail after handler died\n// after\nif !client.is_handler_alive() { client.reconnect().await?; }\nclient.send_order(payload)?;","handlingStrategy":"try-catch","validationCode":"if !ws_client.is_connected() || !ws_client.is_handler_alive() {\n    ws_client.reconnect().await?;\n}","typeGuard":null,"tryCatchPattern":"match dispatch.send(req_id, payload) {\n    Err(e) if e.to_string().contains(\"handler command channel closed\") => {\n        pending.remove(&req_id);\n        reconnect_and_resubmit().await?;\n    }\n    r => r?,\n}","preventionTips":["Supervise the WS handler task and auto-reconnect on unexpected exit.","Pause order submission while disconnected; queue and flush after reconnect.","Track connection state and check it before every submission.","Alert on this error: it means the background task died, not just one bad request."],"tags":["kraken","websocket","channel-closed","order-submission","connectivity"],"backgroundTag":"broken-pipe","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"}