{"record":{"id":"9600396c17ff41f2","repo":"nautechsystems/nautilus_trader","slug":"failed-to-terminate-deribit-execution-tasks-e","errorCode":null,"errorMessage":"Failed to terminate Deribit execution tasks: {e}","messagePattern":"Failed to terminate Deribit execution tasks: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/deribit/src/execution.rs","lineNumber":200,"sourceCode":"        }\n    }\n\n    /// Aborts all pending async tasks.\n    fn abort_pending_tasks(&self) {\n        self.pending_tasks.begin_shutdown();\n    }\n\n    fn abort_session_tasks(&self) {\n        self.session_tasks.begin_shutdown();\n        self.ws_client.begin_shutdown();\n    }\n\n    async fn await_pending_tasks(&self) -> anyhow::Result<()> {\n        self.pending_tasks.begin_shutdown();\n        self.pending_tasks\n            .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to terminate Deribit execution tasks: {e}\"))?;\n        Ok(())\n    }\n\n    async fn await_session_tasks(&self) -> anyhow::Result<()> {\n        self.session_tasks.begin_shutdown();\n        self.session_tasks\n            .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to terminate Deribit session tasks: {e}\"))?;\n        Ok(())\n    }\n\n    async fn teardown_partial_connect(&self) -> anyhow::Result<()> {\n        self.abort_session_tasks();\n        self.abort_pending_tasks();\n\n        let mut errors = Vec::new();\n        if let Err(e) = self.ws_client.close().await {","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/deribit/src/execution.rs#L182-L218","documentation":"During execution-client shutdown, `await_pending_tasks` asks the task manager to finish all pending trading tasks within tight deadlines (1s collect / 2s terminate). If tasks don't stop in time, `finish_shutdown` errors and is wrapped with this message at execution.rs:200. It is surfaced through `connect()` (which awaits pending tasks when the task generation isn't open), indicating stale tasks from a prior session blocked a clean connect.","triggerScenarios":"Reconnecting while previous pending tasks (order/trade handlers, request futures) are still running and refuse to finish within the 1s+2s shutdown windows; shutdown called while a pending task is blocked on a hung WebSocket request.","commonSituations":"Rapid disconnect/reconnect cycles on flaky networks; a Deribit API call stuck without a response; process reusing the execution client after a previous session's tasks stalled; overloaded runtime delaying task completion past the deadlines.","solutions":["Retry the connect after a short delay so stalled tasks get a chance to be aborted/reaped.","Investigate why a pending task hung (typically an unanswered WebSocket request) and add upstream timeouts.","Call the abort path (e.g. `abort_pending_tasks`) before reconnecting to force-cancel stragglers.","If deadlines are too tight for your workload, run reconnect logic in a fresh execution-client instance instead of reusing one."],"exampleFix":"// before\nmatch client.connect().await {\n    Err(e) => return Err(e),\n    Ok(()) => {}\n}\n\n// after\nif let Err(e) = client.connect().await {\n    if e.to_string().contains(\"Failed to terminate Deribit execution tasks\") {\n        tokio::time::sleep(Duration::from_millis(500)).await;\n        client.abort_pending_tasks();\n    }\n    client.connect().await?;\n}","handlingStrategy":"retry","validationCode":"// No direct pre-check exists; ensure no connect() is already in flight:\nassert!(!connect_in_progress.load(Ordering::SeqCst), \"connect already running\");","typeGuard":null,"tryCatchPattern":"if let Err(e) = client.connect().await {\n    if e.to_string().contains(\"Failed to terminate Deribit execution tasks\") {\n        client.abort_pending_tasks();\n        tokio::time::sleep(Duration::from_millis(500)).await;\n        client.connect().await?;\n    } else {\n        return Err(e);\n    }\n}","preventionTips":["Never call connect() concurrently; serialize with a mutex.","Add application-level timeouts to operations so tasks can't hang indefinitely.","Abort pending tasks explicitly before reconnecting after a shutdown error.","Avoid tight reconnect loops; use exponential backoff."],"tags":["task-shutdown","timeout","reconnect","deribit"],"backgroundTag":"invalid-state-transition","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"}