nautechsystems/nautilus_trader · error · anyhow::Error

Failed to start Hyperliquid data task generation

Error message

Failed to start Hyperliquid data task generation: {e}

What it means

Same connect sequence as error 3102 but for the `pending_tasks` manager: `pending_tasks.start_generation()` failed while starting a new generation of background (pending) data tasks. Connect aborts with this error after the session generation already started, leaving the client not fully connected.

Solutions

  1. Ensure full teardown before reconnecting (await disconnect to completion).
  2. Serialize the connect/disconnect lifecycle; never interleave them.
  3. Recreate the data client if the task manager remains in a bad state.
  4. Check logs for the earlier pending-task shutdown error that left the stale state.

Example fix

// before
let _ = client.disconnect().await; // ignoring incomplete teardown
client.connect().await?;
// after
client.disconnect().await?; // propagate teardown errors first
client.connect().await?;
Defensive patterns

Strategy: try-catch

Try / catch

// serialize lifecycle; on pending-generation failure, tear down and retry once
if let Err(e) = client.connect().await {
    if e.to_string().contains("task generation") {
        let _ = client.disconnect().await;
        tokio::time::sleep(Duration::from_millis(500)).await;
        client.connect().await?;
    } else {
        return Err(e);
    }
}

Prevention

When it happens

Trigger: Calling connect when the pending-task registry cannot start a new generation — stale generation state from an incomplete previous shutdown, or concurrent connect/teardown racing on the same client.

Common situations: Rapid reconnect loops in a supervisor; calling connect while a previous disconnect's `await_pending_tasks` was still timing out; sharing one client across tasks.

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/fe810839f81f9b65. Report an issue: GitHub.

Appendix: source

Thrown at crates/adapters/hyperliquid/src/data.rs:643

            // task so its receiver and subscription registries cannot belong
            // to the previous generation.
            self.ws_client.begin_shutdown();
            self.ws_client
                .disconnect()
                .await
                .context("failed to tear down Hyperliquid WebSocket before reconnect")?;
            self.ws_client.reset_runtime_state();
            self.abort_session_tasks();
            self.abort_pending_tasks();
            let (session_result, pending_result) =
                tokio::join!(self.await_session_tasks(), self.await_pending_tasks());
            session_result?;
            pending_result?;
            self.session_tasks.start_generation().map_err(|e| {
                anyhow::anyhow!("Failed to start Hyperliquid data session generation: {e}")
            })?;
            self.pending_tasks.start_generation().map_err(|e| {
                anyhow::anyhow!("Failed to start Hyperliquid 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();
            });

        register_hyperliquid_custom_data();

        let instruments = self
            .bootstrap_instruments()
            .await
            .context("failed to bootstrap instruments")?;

View on GitHub (pinned to 18893faf8b)