nautechsystems/nautilus_trader · error
Failed to terminate Betfair session tasks: {e}
Error message
Failed to terminate Betfair session tasks: {e} What it means
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.
Source
Thrown at crates/adapters/betfair/src/execution.rs:536
self.session_tasks.begin_shutdown();
self.account_refresh_tx = None;
}
async fn await_pending_tasks(&self) -> anyhow::Result<()> {
self.pending_tasks.begin_shutdown();
self.pending_tasks
.finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))
.await
.map_err(|e| anyhow::anyhow!("Failed to terminate Betfair execution tasks: {e}"))?;
Ok(())
}
async fn await_session_tasks(&self) -> anyhow::Result<()> {
self.session_tasks.begin_shutdown();
self.session_tasks
.finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))
.await
.map_err(|e| anyhow::anyhow!("Failed to terminate Betfair session tasks: {e}"))?;
Ok(())
}
async fn teardown_partial_connect(&mut self) -> anyhow::Result<()> {
self.abort_session_tasks();
self.abort_pending_tasks();
if let Some(control) = &self.socket_control {
control.deregister();
}
if let Some(client) = self.stream_client.as_ref() {
match client.close().await {
Ok(()) => self.stream_client = None,
Err(e) => self
.shutdown_errors
.push(format!("stream shutdown failed: {e}")),
}View on GitHub (pinned to 18893faf8b)
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
Example fix
// before self.session_tasks.finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)).await?; // after self.session_tasks.finish_shutdown(Duration::from_secs(5), Duration::from_secs(10)).await?;
Defensive patterns
Strategy: try-catch
Validate before calling
if !self.session_tasks.is_open() { return Ok(()); } // nothing to shut down Try / catch
if let Err(e) = exec_client.await_session_tasks().await {
log::error!("session task shutdown: {e}; aborting");
exec_client.abort_session_tasks();
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- Failed to terminate Betfair execution tasks: {e}
- Failed to terminate AX execution session tasks: {e}
- Failed to finish Betfair data command tasks: {e}
- Failed to terminate Hyperliquid data tasks: {e}
- Close command should not be drained
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/01b04c4658ab8672.
Report an issue: GitHub.