nautechsystems/nautilus_trader · error

failed to connect Binance Spot SBE WebSocket

Error message

failed to connect Binance Spot SBE WebSocket: {e}

What it means

The Binance Spot data client failed to establish the SBE (Simple Binary Encoding) WebSocket connection during connect(). The underlying WebSocket error is logged with debug formatting and wrapped in an anyhow error that aborts the async connection session, so the data client cannot start streaming market data.

Solutions

  1. Check network reachability of the Binance WebSocket endpoint (curl the REST base / DNS resolve) and fix firewall/proxy rules.
  2. Inspect the log line 'Binance Spot SBE WebSocket connection failed: {e:?}' for the root cause (TLS, timeout, HTTP 451/403).
  3. Confirm you are not in a geo-restricted region or use an appropriately located deployment.
  4. Retry with backoff; Binance occasionally drops connections during maintenance windows.
  5. Verify adapter config (SBE vs JSON mode, URL) matches your environment.

Example fix

// before
client.connect().await?;
// after
match client.connect().await {
    Ok(()) => log::info!("connected"),
    Err(e) if e.to_string().contains("failed to connect Binance Spot SBE WebSocket") => {
        log::warn!("transient WS failure, retrying: {e}");
        tokio::time::sleep(Duration::from_secs(5)).await;
        client.connect().await?;
    }
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-connect reachability probe
let host = "stream.binance.com";
tokio::net::TcpStream::connect((host, 9443)).await.expect("Binance WS endpoint unreachable");

Type guard

fn is_ws_connect_error(err: &anyhow::Error) -> bool {
    err.to_string().contains("failed to connect Binance Spot")
}

Try / catch

match client.connect().await {
    Ok(()) => {},
    Err(e) if is_ws_connect_error(&e) => retry_with_backoff(|| client.connect(), 3, Duration::from_secs(2)).await?,
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling BinanceSpotDataClient::connect() when SpotWsClient is the Sbe variant and ws_client.connect() fails — typically network unreachable, DNS failure, TLS handshake failure, or the Binance wss endpoint rejecting/closing the connection.

Common situations: No internet or firewall/proxy blocking wss://stream.binance.com:9443; Binance geo-blocking (e.g. US IPs hitting 451); wrong URL configured; transient Binance outage; missing keepalive causing early disconnect during handshake.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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

Appendix: source

Thrown at crates/adapters/binance/src/spot/data.rs:1526

            &self.http_client,
            &self.config.instrument_provider,
            self.config.us,
            &self.instruments,
            &self.status_cache,
            &self.ws_client,
            &self.data_sender,
            self.clock,
            false,
        )
        .await?;

        let session_result = async {
            match &mut self.ws_client {
                SpotWsClient::Sbe(ws_client) => {
                    log::info!("Connecting to Binance Spot SBE WebSocket...");
                    ws_client.connect().await.map_err(|e| {
                        log::error!("Binance Spot SBE WebSocket connection failed: {e:?}");
                        anyhow::anyhow!("failed to connect Binance Spot SBE WebSocket: {e}")
                    })?;
                    log::info!("Binance Spot SBE WebSocket connected");

                    let stream = ws_client.stream();
                    let sender = self.data_sender.clone();
                    let insts = self.instruments.clone();
                    let ws_insts = ws_client.instruments_cache();
                    let buffers = self.book_buffers.clone();
                    let book_subs = self.book_subscriptions.clone();
                    let l1_book_subs = self.l1_book_subscriptions.clone();
                    let book_epoch = self.book_epoch.clone();
                    let http = self.http_client.clone();
                    let clock = self.clock;
                    let cancel = self.cancellation_token.clone();
                    let command_spawner = self
                        .command_tasks
                        .spawner()
                        .context("Binance Spot command task admission is closed")?;

View on GitHub (pinned to 18893faf8b)