nautechsystems/nautilus_trader · error

Failed to start AX data task generation: {e}

Error message

Failed to start AX data task generation: {e}

What it means

Immediately after starting the session task generation on connect, the pending task group's start_generation is called. If that fails, connect aborts with "Failed to start AX data task generation". The client then cannot register subscription tasks for the new session.

Source

Thrown at crates/adapters/architect_ax/src/data.rs:460

        {
            log::debug!("Already connected {}", self.client_id);
            return Ok(());
        }

        log::info!("Connecting {}", self.client_id);

        if self.cancellation_token.is_cancelled()
            || !self.pending_tasks.is_open()
            || !self.session_tasks.is_open()
            || !self.funding_rate_cancellations.is_empty()
        {
            self.teardown_partial_connect().await?;
            self.session_tasks
                .start_generation()
                .map_err(|e| anyhow::anyhow!("Failed to start AX data session generation: {e}"))?;
            self.pending_tasks
                .start_generation()
                .map_err(|e| anyhow::anyhow!("Failed to start AX data task generation: {e}"))?;
            self.cancellation_token = CancellationToken::new();
        }
        let cancellation_token = self.cancellation_token.clone();
        let ws_client = self.ws_client.clone();
        let setup_guard =
            TaskGroupGuard::new(&[&self.session_tasks, &self.pending_tasks], move || {
                cancellation_token.cancel();
                ws_client.begin_shutdown();
            });

        let credential = if self.config.has_api_credentials() {
            let credential = Credential::resolve(
                self.config.api_key.clone().map(|value| value.into_inner()),
                self.config
                    .api_secret
                    .clone()
                    .map(|value| value.into_inner()),
            )

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Serialize connect/disconnect calls (mutex or single owner) to prevent concurrent generation starts
  2. Retry connect; if it persists, recreate the client to reset task group state
  3. Ensure teardown_partial_connect fully clears pending_tasks before the next connect
  4. Inspect the inner start_generation error for the specific cause

Example fix

// before
let (a, b) = tokio::join!(client_a.connect(), client_b.connect()); // same client shared
// after
static CONNECT: Mutex<()> = Mutex::new(()); // serialize connects
let _g = CONNECT.lock().await;
client.connect().await?;
Defensive patterns

Strategy: retry

Validate before calling

// Rust
// guard: only one connect in flight at a time
let _guard = connect_lock.lock().await;

Try / catch

// Rust
match client.connect().await {
    Err(e) if e.to_string().contains("task generation") => {
        client.disconnect().await.ok(); // reset state then retry once
        client.connect().await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling connect when the pending task group cannot begin a new generation — e.g. group left in an inconsistent state by an earlier partial teardown or a concurrent connect.

Common situations: Rapid disconnect/reconnect cycles; concurrent connect invocations; a previous connect that failed between the session and pending start_generation calls, leaving state torn.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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