{"record":{"id":"45c2de0d1e719825","repo":"nautechsystems/nautilus_trader","slug":"architect-ax-data-websocket-handler-did-not-stop-a","errorCode":null,"errorMessage":"Architect AX data WebSocket handler did not stop after abort","messagePattern":"Architect AX data WebSocket handler did not stop after abort","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/architect_ax/src/websocket/data/client.rs","lineNumber":1081,"sourceCode":"        self.signal.store(true, Ordering::Release);\n\n        let outcome = self\n            .task_handle\n            .finish(Duration::from_secs(2), Duration::from_secs(2))\n            .await;\n\n        *self.reconnect_headers.lock() = None;\n\n        if let Some(control) = &self.socket_control {\n            control.deregister();\n        }\n\n        match outcome {\n            None | Some(TaskJoinOutcome::Completed(()) | TaskJoinOutcome::Aborted) => Ok(()),\n            Some(TaskJoinOutcome::Failed(error)) => Err(anyhow::anyhow!(\n                \"Architect AX data WebSocket handler failed: {error}\"\n            )),\n            Some(TaskJoinOutcome::Incomplete) => Err(anyhow::anyhow!(\n                \"Architect AX data WebSocket handler did not stop after abort\"\n            )),\n        }\n    }\n\n    async fn send_cmd(&self, cmd: HandlerCommand) -> AxWsResult<()> {\n        let guard = self.cmd_tx.read().await;\n        guard\n            .send(cmd)\n            .map_err(|e| AxWsClientError::ChannelError(e.to_string()))\n    }\n}\n\nimpl Drop for AxMdWebSocketClient {\n    fn drop(&mut self) {\n        if Arc::strong_count(&self.task_handle) == 1 && !self.task_handle.is_empty() {\n            self.cancellation_token.load().cancel();\n            self.signal.store(true, Ordering::Release);","sourceCodeStart":1063,"sourceCodeEnd":1099,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/architect_ax/src/websocket/data/client.rs#L1063-L1099","documentation":"Returned by the Architect AX data WebSocket client's close() when, after issuing an abort to the handler task, the join outcome is TaskJoinOutcome::Incomplete — meaning the task did not finish within the abort/join window.","triggerScenarios":"Calling close() and the handler task neither completes, fails, nor acknowledges the abort in time (e.g. it is stuck in a long await, a blocking loop, or ignoring the abort signal).","commonSituations":"Handler blocked on a network read without honoring cancellation; a deadlock between the handler and command channel; slow/hung remote server keeping the task alive during shutdown.","solutions":["Check the handler loop for awaits or blocking calls that ignore the abort/cancellation token","Increase the shutdown timeout if it is legitimately slow, or add cooperative cancellation checks in the handler loop","Look for deadlock between handler and command channels (e.g. unbounded queue consumption ordering)","Restart the client/connection; the task may be leaked and should be reported as a bug if reproducible"],"exampleFix":"// before\nloop {\n    let msg = ws.next().await; // ignores cancellation\n    ...\n}\n// after\nloop {\n    tokio::select! {\n        _ = cancel_token.cancelled() => break,\n        msg = ws.next() => { ... }\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust\nmatch client.close().await {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"did not stop after abort\") => {\n        tracing::error!(\"handler task leaked: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use tokio::select! with the cancellation token in every long await in the handler","Avoid blocking (std::thread::sleep, sync IO) inside async handler code","Keep handler waits bounded with timeouts so tasks can always reach an exit point","Test shutdown under slow-network conditions"],"tags":["websocket","async","timeout","shutdown"],"backgroundTag":"task-did-not-stop-after-abort","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"}