nautechsystems/nautilus_trader · error

failed to register Coinbase WebSocket consumption task

Error message

failed to register Coinbase WebSocket consumption task

What it means

This error is returned by spawn_ws when the Coinbase WebSocket consumption task fails to register with the session task spawner, but the rollback disconnect (ws_client.disconnect()) succeeded. The original spawn error is the source; the context indicates the startup was cleanly rolled back — no lingering connection should remain. It surfaces from connect().

Source

Thrown at crates/adapters/coinbase/src/data/mod.rs:303

                                log::debug!("WebSocket output channel closed");
                                break;
                            }
                        }
                    }
                }
            }

            log::debug!("Coinbase WebSocket consumption loop finished");
        };

        if let Err(e) = self.session_tasks.spawn(future) {
            if let Err(shutdown_error) = self.ws_client.disconnect().await {
                return Err(anyhow::Error::new(e).context(format!(
                    "failed to register Coinbase WebSocket consumption task; startup rollback \
                     failed: {shutdown_error}"
                )));
            }
            return Err(anyhow::Error::new(e)
                .context("failed to register Coinbase WebSocket consumption task"));
        }
        log::debug!("WebSocket consumption task registered");
        Ok(())
    }

    async fn teardown_partial_connect(&mut self) -> anyhow::Result<()> {
        self.cancellation_token.cancel();
        self.session_tasks.begin_shutdown();
        self.command_tasks.begin_shutdown();
        self.deriv_polls.shutdown();
        self.ws_client.begin_shutdown();

        let (tasks_result, polls_result) =
            tokio::join!(self.finish_tasks(), self.deriv_polls.finish_shutdown());

        if let Err(e) = tasks_result {
            self.shutdown_errors.push(e.to_string());

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Fix client lifecycle: create and connect the client within a live session scope, don't reuse after shutdown
  2. Check the chained spawn error source for the task-group failure reason
  3. Ensure the tokio runtime is alive and not being torn down during connect()
  4. Retry connect() with a freshly constructed data client
  5. Look for concurrent connect/shutdown calls racing on the same client
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard: only connect a client with a live session and runtime
if session_is_closed() || runtime_is_shutting_down() {
    return Err(anyhow!("refusing to connect Coinbase data client during shutdown"));
}

Type guard

fn is_clean_rollback(err: &anyhow::Error) -> bool {
    err.to_string().contains("failed to register Coinbase WebSocket consumption task")
        && !err.to_string().contains("startup rollback failed")
}

Try / catch

match connect(client).await {
    Err(e) if is_clean_rollback(&e) => {
        // spawn failed but disconnect succeeded: safe to retry with fresh client
        retry_with_backoff(|| connect(new_client())).await
    }
    other => other,
}

Prevention

When it happens

Trigger: session_tasks.spawn(future) returns Err (closed/aborted task group, runtime shutdown) while self.ws_client.disconnect().await succeeds.

Common situations: Connecting a Coinbase data client after its session task group was dropped; tokio runtime cancellation during startup; calling connect() concurrently with shutdown; lifecycle misuse of the live data client.

Related errors


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