nautechsystems/nautilus_trader · error
Failed to start Betfair session generation: {e}
Error message
Failed to start Betfair session generation: {e} What it means
connect (execution client) starts a new task generation for session_tasks. If start_generation fails (e.g. the group is still shutting down or the generation is already open), teardown_partial_connect is invoked first and the error is wrapped with this message.
Source
Thrown at crates/adapters/betfair/src/execution.rs:1448
client.begin_shutdown();
}
self.clear_resync_state();
log::info!("Stopped: client_id={}", self.core.client_id);
Ok(())
}
async fn connect(&mut self) -> anyhow::Result<()> {
if self.core.is_connected() && self.session_tasks.is_open() && self.pending_tasks.is_open()
{
return Ok(());
}
if !self.session_tasks.is_open() || !self.pending_tasks.is_open() {
self.teardown_partial_connect().await?;
self.session_tasks
.start_generation()
.map_err(|e| anyhow::anyhow!("Failed to start Betfair session generation: {e}"))?;
self.pending_tasks
.start_generation()
.map_err(|e| anyhow::anyhow!("Failed to start Betfair task generation: {e}"))?;
}
let http_cancellation = self.http_client.cancellation_token();
let setup_guard =
TaskGroupGuard::new(&[&self.session_tasks, &self.pending_tasks], move || {
http_cancellation.cancel();
});
register_betfair_custom_data();
let session_token_result = async {
self.http_client
.connect()
.await
.map_err(|e| anyhow::anyhow!("{e}"))?;View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure connect/disconnect calls are strictly sequential
- Wait for teardown_partial_connect of the previous attempt to finish before reconnecting
- Inspect the inner error `e` from start_generation for the registry state
Example fix
// before: overlapping connects tokio::join!(client.connect(), client.connect()); // after client.connect().await?; // later client.disconnect().await?; client.connect().await?;
Defensive patterns
Strategy: validation
Validate before calling
if client.is_connected() { return Ok(()); } // avoid double connect Type guard
fn can_connect(client: &BetfairExecClient) -> bool {
!client.is_connected() && !client.is_shutting_down()
} Try / catch
if let Err(e) = client.connect().await {
if e.to_string().contains("session generation") {
tokio::time::sleep(Duration::from_secs(1)).await;
client.connect().await?;
} else { return Err(e); }
} Prevention
- Use a mutex/flag so connect runs once
- Always run teardown to completion before reconnect
- Avoid spawning connect and disconnect concurrently
When it happens
Trigger: session_tasks or pending_tasks group is not open (mid-shutdown or never initialized) and start_generation still fails — concurrent connect calls, or a prior connect's teardown not yet finished.
Common situations: Calling connect twice without disconnect; reconnect racing a prior shutdown; a previous failed connect leaving the groups in a half-open state.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Failed to start Betfair task generation: {e}
- Failed to start Betfair data session tasks: {e}
- Failed to start Betfair data command tasks: {e}
- Failed to start Hyperliquid task generation: {e}
- Failed to start Hyperliquid execution session generation: {e
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f5461178f8c9365c.
Report an issue: GitHub.