nautechsystems/nautilus_trader · error

Failed to start Coinbase task generation: {e}

Error message

Failed to start Coinbase task generation: {e}

What it means

Inside connect(), after awaiting and terminating the previous pending-task generation, the client calls `start_generation` to open a fresh generation of execution tasks. If the task set refuses to start, this error is raised.

Source

Thrown at crates/adapters/coinbase/src/execution.rs:376

    fn oms_type(&self) -> OmsType {
        self.core.oms_type
    }

    fn get_account(&self) -> Option<AccountAny> {
        self.core.cache().account_owned(&self.core.account_id)
    }

    async fn connect(&mut self) -> anyhow::Result<()> {
        if self.core.is_connected() && self.pending_tasks.is_open() && self.session_tasks.is_open()
        {
            return Ok(());
        }

        if !self.pending_tasks.is_open() {
            self.await_pending_tasks().await?;
            self.pending_tasks
                .start_generation()
                .map_err(|e| anyhow::anyhow!("Failed to start Coinbase task generation: {e}"))?;
        }

        if !self.session_tasks.is_open() || !self.session_tasks.is_empty() {
            self.abort_session_tasks();
            self.ws_user
                .disconnect()
                .await
                .context("failed to close stale Coinbase user WebSocket")?;
            self.await_session_tasks().await?;
            self.session_tasks
                .start_generation()
                .map_err(|e| anyhow::anyhow!("Failed to start Coinbase session generation: {e}"))?;
        }
        let ws_user = self.ws_user.clone();
        let setup_guard =
            TaskGroupGuard::new(&[&self.session_tasks, &self.pending_tasks], move || {
                ws_user.begin_shutdown();
            });

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Serialize connect() calls (single owner task or mutex)
  2. Ensure disconnect/finish_shutdown completed before reconnecting
  3. Read the inner `{e}` from start_generation in logs
  4. Recreate the execution client if the generation state is corrupted
  5. Check for concurrent engine start/stop racing the adapter

Example fix

// before
let c = client.clone();
tokio::spawn(async move { c.connect().await });
client.connect().await?; // duplicate connect
// after
client.connect().await?; // exactly one connect per client
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = client.connect().await {
    if e.to_string().contains("Failed to start Coinbase task generation") {
        // unrecoverable state race: rebuild client
        client = CoinbaseExecClient::new(...).await?;
        client.connect().await?;
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: connect() invoked when the pending task set is closed but its internal state does not permit starting a new generation — e.g. shutdown not fully observed, or concurrent connect calls racing on the same task set.

Common situations: Two components calling connect() on the same execution client simultaneously; reconnect logic that skips proper disconnect/teardown ordering.

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