nautechsystems/nautilus_trader · error

Failed to start Betfair data command tasks: {e}

Error message

Failed to start Betfair data command tasks: {e}

What it means

Identical to error 1751 but for the command TaskGroup: command_tasks.start_generation() failed in prepare_task_groups. The command group hosts control-plane tasks (subscribes, commands); without a new generation, connect cannot spawn them.

Source

Thrown at crates/adapters/betfair/src/data.rs:242

            self.command_tasks
                .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)),
        );
        session_result
            .map_err(|e| anyhow::anyhow!("Failed to finish Betfair data session tasks: {e}"))?;
        command_result
            .map_err(|e| anyhow::anyhow!("Failed to finish Betfair data command tasks: {e}"))?;
        Ok(())
    }

    async fn prepare_task_groups(&mut self) -> anyhow::Result<()> {
        if !self.session_tasks.is_open() || !self.command_tasks.is_open() {
            self.teardown_partial_connect().await?;
            self.session_tasks
                .start_generation()
                .map_err(|e| anyhow::anyhow!("Failed to start Betfair data session tasks: {e}"))?;
            self.command_tasks
                .start_generation()
                .map_err(|e| anyhow::anyhow!("Failed to start Betfair data command tasks: {e}"))?;
        }
        Ok(())
    }

    fn begin_stream_shutdown(&self) {
        for stream in self.stream_shutdowns.lock().iter() {
            stream.begin_shutdown();
        }
    }

    async fn teardown_partial_connect(&mut self) -> anyhow::Result<()> {
        self.session_tasks.begin_shutdown();
        self.command_tasks.begin_shutdown();
        self.begin_stream_shutdown();
        self.is_connected.store(false, Ordering::Relaxed);

        if let Some(client) = self.cricket_stream_client.as_ref() {
            client.close().await;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the prior disconnect fully drained command tasks before reconnecting (finish_tasks completed without error)
  2. Read the inner `{e}` for the exact TaskGroup state reason
  3. Serialize connect/disconnect calls; do not run them concurrently on the same client
  4. If the group is permanently wedged, rebuild the BetfairDataClient

Example fix

// before
self.command_tasks.start_generation().map_err(|e| anyhow::anyhow!("Failed to start Betfair data command tasks: {e}"))?;
// after
if !self.command_tasks.is_open() {
    self.command_tasks.start_generation().map_err(|e| anyhow::anyhow!("Failed to start Betfair data command tasks: {e}"))?;
}
Defensive patterns

Strategy: retry

Validate before calling

// ensure no connect already in flight
assert!(!client.is_connected(), "previous connect still active");

Try / catch

match client.connect().await {
    Err(e) if e.to_string().contains("Failed to start Betfair data command tasks") => {
        tokio::time::sleep(Duration::from_secs(2)).await;
        client.disconnect().await.ok();
        // then retry connect
    }
    Err(e) => return Err(e),
    Ok(()) => {},
}

Prevention

When it happens

Trigger: connect() -> prepare_task_groups detects command_tasks.is_open() == false after teardown_partial_connect, then start_generation() returns Err because the group is not in a restartable state.

Common situations: Reconnect after a disconnect where the command group shutdown did not finalize; overlapping connect attempts; leftover shutdown errors from a prior failed teardown.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/f2bb46d0f4de5435. Report an issue: GitHub.