nautechsystems/nautilus_trader · error · anyhow::Error

Failed to set Spot public JSON WS client: {e}

Error message

Failed to set Spot public JSON WS client: {e}

What it means

After connecting, create_connection() sends BinanceSpotPublicWsCommand::SetClient(client) to the freshly spawned handler task so it holds the live WS client. This error means that send failed because the handler task/channel is already gone — the handler exited immediately after being spawned.

Source

Thrown at crates/adapters/binance/src/spot/websocket/public_json/client.rs:598

                Some(shutdown_error) => format!(
                    "Failed to start Spot public JSON WS bytes task: {e}; startup rollback failed: \
                     {shutdown_error}"
                ),
                None => format!("Failed to start Spot public JSON WS bytes task: {e}"),
            });
        }

        let mut handler = BinanceSpotPublicWsHandler::new(
            self.signal.clone(),
            cmd_rx,
            bytes_rx,
            subscriptions_state.clone(),
            self.request_id_counter.clone(),
        );

        cmd_tx
            .send(BinanceSpotPublicWsCommand::SetClient(client))
            .map_err(|e| anyhow::anyhow!("Failed to set Spot public JSON WS client: {e}"))?;

        let signal = self.signal.clone();
        let token = cancellation_token.clone();
        let resubscribe_tx = cmd_tx.clone();

        let mut handler_task = TaskSlot::new();
        if let Err(e) = handler_task.spawn(async move {
            loop {
                tokio::select! {
                    () = token.cancelled() => {
                        log::debug!("Spot public JSON handler task cancelled");
                        break;
                    }
                    result = handler.next() => {
                        match result {
                            Some(BinanceSpotPublicWsMessage::Reconnected) => {
                                log::info!("Spot public JSON WebSocket reconnected, restoring subscriptions");
                                let topics = subscriptions_state.all_topics();

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Retry the connect — a fresh create_connection will spawn a new handler; transient races usually resolve.
  2. Check logs for handler task panics during startup and fix the panic root cause.
  3. Ensure the runtime/cancellation token is not cancelled while connections are being established; complete connects before shutdown.
  4. Verify the tokio runtime stays alive for the pool's lifetime (don't drop the runtime that spawned handler tasks).

Example fix

// before
let handle = tokio::spawn(handler_loop()); // runtime may be shutting down
handle.await?;

// after
if runtime_handle.runtime().is_none() || shutdown_flag.load(Ordering::SeqCst) {
    return Err(anyhow!("cannot create connection during shutdown"));
}
let handle = runtime_handle.spawn(handler_loop());
handle.await?;
Defensive patterns

Strategy: retry

Try / catch

match client.connect().await {
    Err(e) if e.to_string().contains("Failed to set Spot public JSON WS client") => {
        tokio::time::sleep(Duration::from_millis(500)).await;
        client.connect().await?; // respawn handler and retry SetClient
    }
    r => r,
}

Prevention

When it happens

Trigger: The handler task dies between spawn and the SetClient send — e.g. the cancellation token was already cancelled, the runtime is shutting down, or the handler task panicked on startup.

Common situations: Application/runtime shutdown racing connection setup; a bug or panic in the handler's initialization; spawning the task on a shutting-down tokio runtime; pool partially closed while subscribe()/connect() still runs.

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