{"record":{"id":"01b04c4658ab8672","repo":"nautechsystems/nautilus_trader","slug":"failed-to-terminate-betfair-session-tasks-e","errorCode":null,"errorMessage":"Failed to terminate Betfair session tasks: {e}","messagePattern":"Failed to terminate Betfair session tasks: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/betfair/src/execution.rs","lineNumber":536,"sourceCode":"        self.session_tasks.begin_shutdown();\n        self.account_refresh_tx = None;\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 Betfair 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 Betfair session tasks: {e}\"))?;\n        Ok(())\n    }\n\n    async fn teardown_partial_connect(&mut self) -> anyhow::Result<()> {\n        self.abort_session_tasks();\n        self.abort_pending_tasks();\n\n        if let Some(control) = &self.socket_control {\n            control.deregister();\n        }\n\n        if let Some(client) = self.stream_client.as_ref() {\n            match client.close().await {\n                Ok(()) => self.stream_client = None,\n                Err(e) => self\n                    .shutdown_errors\n                    .push(format!(\"stream shutdown failed: {e}\")),\n            }","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/betfair/src/execution.rs#L518-L554","documentation":"await_session_tasks shuts down the session-task group (login/keep-alive/heartbeat tasks) via begin_shutdown/finish_shutdown with 1s and 2s grace windows. If those tasks cannot be terminated in time or finish_shutdown errors, this anyhow error is returned.","triggerScenarios":"Session keep-alive or reconnect loops not terminating within 1s+2s during teardown; tasks blocked awaiting a hung HTTP call or an unobservable cancellation token.","commonSituations":"Shutting down while a keep-alive request to Betfair hangs; session token renewal in progress at teardown; cancellation token not propagated to the session loop.","solutions":["Increase shutdown durations for slow environments","Ensure all session loops observe the cancellation token so they exit promptly","Call teardown/abort_session_tasks when timeouts persist, then tear down the client"],"exampleFix":"// before\nself.session_tasks.finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)).await?;\n// after\nself.session_tasks.finish_shutdown(Duration::from_secs(5), Duration::from_secs(10)).await?;","handlingStrategy":"try-catch","validationCode":"if !self.session_tasks.is_open() { return Ok(()); } // nothing to shut down","typeGuard":null,"tryCatchPattern":"if let Err(e) = exec_client.await_session_tasks().await {\n    log::error!(\"session task shutdown: {e}; aborting\");\n    exec_client.abort_session_tasks();\n}","preventionTips":["Ensure keep-alive loops observe the cancellation token","Increase grace windows on slow links","Disconnect before process exit to give tasks a chance to finish"],"tags":["rust","betfair","shutdown","timeout","session"],"backgroundTag":"request-timeout","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"}