nautechsystems/nautilus_trader · error

WebSocket output receiver not available

Error message

WebSocket output receiver not available

What it means

During CoinbaseDataAdapter startup, spawn_ws consumes the WebSocket client's output receiver channel exactly once (take_out_rx). If the receiver is already taken or was never created, the adapter rolls back the just-established WebSocket connection and aborts the connect flow. This is an internal lifecycle guard against a double-consumed WS stream.

Source

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

            self.ws_client.update_instrument(instrument.clone()).await;
        }

        log::debug!("Bootstrapped {} instruments", instruments.len());
        Ok(instruments)
    }

    async fn spawn_ws(&mut self) -> anyhow::Result<()> {
        self.ws_client
            .connect()
            .await
            .context("failed to connect to Coinbase WebSocket")?;

        let Some(mut out_rx) = self.ws_client.take_out_rx() else {
            self.ws_client
                .disconnect()
                .await
                .context("failed to roll back Coinbase WebSocket without output receiver")?;
            anyhow::bail!("WebSocket output receiver not available");
        };

        let data_sender = self.data_sender.clone();
        let cancellation_token = self.cancellation_token.clone();
        let status_subs = Arc::clone(&self.instrument_status_subs);

        let future = async move {
            log::debug!("Coinbase WebSocket consumption loop started");

            loop {
                tokio::select! {
                    () = cancellation_token.cancelled() => {
                        log::debug!("WebSocket consumption loop cancelled");
                        break;
                    }
                    msg_opt = out_rx.recv() => {
                        match msg_opt {
                            Some(msg) => dispatch_ws_message(msg, &data_sender, &status_subs),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Create a fresh adapter/WS client for each connect() call instead of reconnecting on a used instance
  2. Ensure only one consumer calls take_out_rx; do not share the ws_client across concurrent connect paths
  3. Check that any prior connect attempt fully tore down (disconnect) before reconnecting, and recreate channels
  4. Inspect logs for the 'failed to roll back Coinbase WebSocket' context to confirm the rollback succeeded

Example fix

// before
let mut adapter = CoinbaseDataClientFactory::create(...);
adapter.connect().await?;
adapter.disconnect().await?;
adapter.connect().await?; // receiver already taken

// after
let mut adapter = CoinbaseDataClientFactory::create(...);
adapter.connect().await?;
adapter.disconnect().await?;
let mut adapter = CoinbaseDataClientFactory::create(...); // fresh client/channel
adapter.connect().await?;
Defensive patterns

Strategy: try-catch

Validate before calling

// before connect: ensure a fresh client
assert!(!adapter.is_connected(), "adapter already connected; recreate it");

Try / catch

match adapter.connect().await {
    Err(e) if e.to_string().contains("output receiver not available") => {
        // recreate the adapter/WS client and retry once
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling connect (via spawn_ws) twice without recreating the adapter's WebSocket client, or constructing the adapter with a ws_client whose output channel was already consumed by another spawn_ws call.

Common situations: Reconnect logic that reuses a stale adapter/WS client after a previous connect; spawning two data tasks sharing one adapter; tests or scripts that call connect() repeatedly on the same instance.

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