nautechsystems/nautilus_trader · error

failed to connect Binance Spot public JSON WebSocket

Error message

failed to connect Binance Spot public JSON WebSocket: {e}

What it means

The Binance Spot data client failed to establish the public JSON WebSocket connection during connect(). The underlying error is logged with debug detail and wrapped in an anyhow error, aborting the connect() session so no market data can stream.

Solutions

  1. Verify the WebSocket endpoint is reachable from your host (DNS + TCP + TLS).
  2. Check the debug log 'Binance Spot public JSON WebSocket connection failed: {e:?}' for the concrete cause.
  3. If geo-blocked (HTTP 451), deploy in a supported region.
  4. Retry with exponential backoff for transient Binance-side drops.
  5. Confirm the adapter is configured for the intended environment (prod vs testnet URL).

Example fix

// before
let client = BinanceSpotDataClient::new_json_public(config);
client.connect().await?;
// after
if let Err(e) = client.connect().await {
    log::error!("spot JSON WS connect failed: {e:#}");
    if e.to_string().contains("failed to connect Binance Spot public JSON WebSocket") {
        tokio::time::sleep(Duration::from_secs(2)).await;
        client.connect().await?;
    } else {
        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 JSON WS endpoint unreachable");

Type guard

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

Try / catch

if let Err(e) = client.connect().await {
    if is_json_ws_connect_error(&e) {
        tokio::time::sleep(Duration::from_secs(5)).await;
        client.connect().await?;
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: Calling connect() when SpotWsClient is the JsonPublic variant and ws_client.connect() fails — network failure, TLS error, endpoint rejecting connection, or invalid stream URL.

Common situations: Firewall or corporate proxy blocking wss://stream.binance.com:9443; Binance geo-restriction responses; DNS misconfiguration; Binance maintenance; wrong environment URL (testnet vs prod).

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

Appendix: source

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

                                        &command_spawner,
                                    );
                                }
                                () = cancel.cancelled() => {
                                    log::debug!("Spot SBE WebSocket stream task cancelled");
                                    break;
                                }
                            }
                        }
                    };
                    self.session_tasks
                        .spawn(future)
                        .context("failed to register Binance Spot SBE stream task")?;
                }
                SpotWsClient::JsonPublic(ws_client) => {
                    log::info!("Connecting to Binance Spot public JSON WebSocket...");
                    ws_client.connect().await.map_err(|e| {
                        log::error!("Binance Spot public JSON WebSocket connection failed: {e:?}");
                        anyhow::anyhow!("failed to connect Binance Spot public JSON WebSocket: {e}")
                    })?;
                    log::info!("Binance Spot public JSON 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)