{"record":{"id":"4448617065037d7a","repo":"nautechsystems/nautilus_trader","slug":"binance-futures-dispatch-task-did-not-stop-after-a","errorCode":null,"errorMessage":"Binance Futures dispatch task did not stop after abort","messagePattern":"Binance Futures dispatch task did not stop after abort","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/futures/execution.rs","lineNumber":947,"sourceCode":"    async fn await_dispatch_task(&self) -> anyhow::Result<()> {\n        let _recovery_guard = self.recovery_lock.lock().await;\n        let mut task_slot = self.ws_task.lock().await;\n        let Some(outcome) = finish_task(\n            &mut task_slot,\n            Duration::from_secs(1),\n            Duration::from_secs(2),\n        )\n        .await\n        else {\n            return Ok(());\n        };\n\n        match outcome {\n            TaskJoinOutcome::Completed(()) | TaskJoinOutcome::Aborted => Ok(()),\n            TaskJoinOutcome::Failed(e) => {\n                Err(anyhow::anyhow!(\"Binance Futures dispatch task failed: {e}\"))\n            }\n            TaskJoinOutcome::Incomplete => Err(anyhow::anyhow!(\n                \"Binance Futures dispatch task did not stop after abort\"\n            )),\n        }\n    }\n\n    async fn close_listen_key_slot(\n        &self,\n        slot: &RwLock<Option<SecretString>>,\n        context: &str,\n    ) -> anyhow::Result<()> {\n        let key = slot.read().clone();\n        let Some(key) = key else {\n            return Ok(());\n        };\n\n        self.http_client\n            .close_listen_key(key.expose_secret())\n            .await","sourceCodeStart":929,"sourceCodeEnd":965,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/futures/execution.rs#L929-L965","documentation":"await_dispatch_task aborted the dispatch task and waited on its join handle; a TaskJoinOutcome::Incomplete means the task neither completed nor acknowledged the abort within the allowed window. This indicates a wedged dispatch loop that ignored cancellation during connect/disconnect.","triggerScenarios":"Calling connect or disconnect when the dispatch task is blocked in a non-cancellation-safe operation (e.g. a lock held across await, a blocking call in the async loop) and does not finish after abort is requested.","commonSituations":"Deadlocks in runtime under heavy load, blocking I/O inside the async dispatch loop, or tokio runtime starvation preventing the aborted task from being polled to completion.","solutions":["Retry the disconnect after the runtime settles","Check for blocking calls or long-held locks in any custom handlers feeding the dispatch loop","Ensure the tokio runtime has adequate worker threads and is not starved","Upgrade to the latest nautilus_trader version; report a bug if it reproduces, as this indicates a cancellation-safety issue"],"exampleFix":"// before\nclient.disconnect().await?; // may hang/fail if dispatch task is wedged\n// after\nif let Err(e) = client.disconnect().await {\n    tracing::warn!(\"disconnect incomplete: {e:#}\");\n    tokio::time::sleep(Duration::from_secs(1)).await;\n    client.disconnect().await?;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = client.disconnect().await {\n    if e.to_string().contains(\"did not stop after abort\") {\n        tokio::time::sleep(Duration::from_secs(1)).await;\n        client.disconnect().await?;\n    } else { return Err(e); }\n}","preventionTips":["Avoid blocking calls inside async message handlers","Size the tokio runtime adequately to avoid task starvation","Report reproducible cases; this points to a cancellation-safety bug"],"tags":["binance","dispatch","cancellation","task-timeout"],"backgroundTag":"request-timeout","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}