nautechsystems/nautilus_trader · error

Failed to send SetClient command: {e}

Error message

Failed to send SetClient command: {e}

What it means

After establishing the WebSocket connection, connect() injects the freshly built client into the running handler task via a HandlerCommand::SetClient message on a channel. If that send fails (receiver dropped), the adapter cannot hand off the authenticated client and bails with this error.

Source

Thrown at crates/adapters/coinbase/src/websocket/client.rs:296

            .config(cfg)
            .message_handler(message_handler)
            .keyed_quotas(keyed_quotas)
            .default_quota(*COINBASE_WS_CONNECTION_QUOTA)
            .maybe_state_sink(self.socket_control.as_ref().map(SocketControl::sink))
            .connect()
            .await?;

        let (cmd_tx, cmd_rx) = tokio::sync::mpsc::unbounded_channel::<HandlerCommand>();
        let (out_tx, out_rx) = tokio::sync::mpsc::unbounded_channel::<NautilusWsMessage>();

        *self.cmd_tx.write().await = cmd_tx.clone();
        self.out_rx = Some(out_rx);
        self.connection_mode.store(client.connection_mode_atomic());
        let reconnect_handle = client.reconnect_handle();
        log::debug!("Coinbase WebSocket connected: {}", self.url);

        if let Err(e) = cmd_tx.send(HandlerCommand::SetClient(client)) {
            anyhow::bail!("Failed to send SetClient command: {e}");
        }

        if let Some(control) = &self.socket_control {
            control.register(move || reconnect_handle.request_reconnect());
        }

        let instruments_vec: Vec<InstrumentAny> =
            self.instruments.load().values().cloned().collect();

        if !instruments_vec.is_empty()
            && let Err(e) = cmd_tx.send(HandlerCommand::InitializeInstruments(instruments_vec))
        {
            log::error!("Failed to send InitializeInstruments: {e}");
        }

        // Restore bar type registrations from previous session
        for (key, bar_type) in &self.bar_types {
            if let Err(e) = cmd_tx.send(HandlerCommand::AddBarType {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the handler logs just before this error for the underlying disconnect cause
  2. Verify network stability to the Coinbase WebSocket endpoint
  3. Retry the connection; if recurring, ensure only one connect loop owns the client lifecycle
Defensive patterns

Strategy: retry

Try / catch

match ws.connect().await {
    Err(e) if e.to_string().contains("Failed to send SetClient") => {
        log::warn!("handler died during setup, retrying: {e}");
        // reconnect with backoff
    }
    other => other.map(|_| ()),
}

Prevention

When it happens

Trigger: The handler task exited/closed its command channel before SetClient was sent — usually because the handler died immediately after spawn (e.g. connection dropped, panic) while connect() was still setting up.

Common situations: WebSocket server accepted then immediately closed the connection; handler panicked during initialization; rapid reconnect storm closed the channel between iterations.

Related errors


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