nautechsystems/nautilus_trader · critical
failed to connect Binance Futures market WebSocket: {e}
Error message
failed to connect Binance Futures market WebSocket: {e} What it means
Raised during `connect()` when the Binance Futures market WebSocket client fails to establish its connection; the underlying transport error is wrapped with anyhow and also logged at ERROR level (`Binance Futures market WebSocket connection failed: {e:?}`) just above. Because this sits in the data client's connect sequence (after the instrument catalogue refresh), the whole connect fails and no streams start. The real cause is in the wrapped error: DNS/TLS/network failure, a firewall or proxy blocking wss, Binance rejecting the handshake, region-restricted access, or an endpoint/credential mismatch such as production keys against a testnet URL.
Source
Thrown at crates/adapters/binance/src/futures/data.rs:1533
self.cancellation_token = CancellationToken::new();
Self::refresh_instrument_catalogue(
&self.http_client,
&self.config.instrument_provider,
&self.instruments,
&self.status_cache,
&self.ws_client,
&self.ws_public_client,
&self.data_sender,
self.clock,
false,
)
.await?;
log::info!("Connecting to Binance Futures market WebSocket...");
self.ws_client.connect().await.map_err(|e| {
log::error!("Binance Futures market WebSocket connection failed: {e:?}");
anyhow::anyhow!("failed to connect Binance Futures market WebSocket: {e}")
})?;
log::info!("Binance Futures market WebSocket connected");
log::info!("Connecting to Binance Futures public WebSocket...");
self.ws_public_client.connect().await.map_err(|e| {
log::error!("Binance Futures public WebSocket connection failed: {e:?}");
anyhow::anyhow!("failed to connect Binance Futures public WebSocket: {e}")
})?;
log::info!("Binance Futures public WebSocket connected");
// Spawn market stream handler
let stream = self.ws_client.stream();
let sender = self.data_sender.clone();
let insts = self.instruments.clone();
let ws_insts = self.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();View on GitHub (pinned to a4b06ed870)
Solutions
- Read the wrapped `{e}` in the log line above to identify the true cause (DNS vs TLS vs HTTP 401/403 vs timeout)
- Fix environment: ensure wss://fstream.binance.com (or the testnet host) is reachable from the host, open firewall/proxy, set HTTPS_PROXY if a proxy is required
- If the error is auth/region related (401/403): verify api_key/api_secret, enable futures permission on the key, and make sure testnet=True matches testnet keys
- Retry connect with exponential backoff for transient outages instead of crashing the node
Example fix
# before: single connect attempt, any hiccup kills startup
await node.run() # connect raises: failed to connect Binance Futures market WebSocket: {e}
# after: correct environment matching + retry with backoff, abort on auth errors
config = BinanceFuturesDataClientConfig(
api_key=os.environ['BINANCE_API_KEY'],
api_secret=os.environ['BINANCE_API_SECRET'],
testnet=True, # must match the environment your keys belong to
)
for attempt in range(6):
try:
await node.run()
break
except Exception as e:
msg = str(e)
if '401' in msg or '403' in msg or 'signature' in msg.lower():
raise RuntimeError('Binance auth/region problem: check keys, futures permission, testnet flag') from e
await asyncio.sleep(min(2 ** attempt, 30)) Defensive patterns
Strategy: retry
Validate before calling
import socket
def binance_ws_reachable(host: str = 'fstream.binance.com', port: int = 443, timeout: float = 5.0) -> bool:
"""Preflight: can this host open a TCP connection to the WS endpoint?"""
try:
with socket.create_connection((host, port), timeout=timeout):
return True
except OSError:
return False
if not binance_ws_reachable():
raise RuntimeError('fstream.binance.com unreachable — fix network/firewall/region before starting the client') Try / catch
# transient WS failures: retry the full connect with backoff; abort on auth/region causes
last = None
for attempt in range(6):
try:
await node.run() # data client connect happens here
break
except Exception as e:
if 'failed to connect Binance Futures market WebSocket' not in str(e):
raise
last = e
if any(tok in str(e) for tok in ('401', '403', 'signature', 'Unauthorized')):
raise RuntimeError('Binance rejected the WS handshake: check keys, futures permission, testnet flag, region access') from e
await asyncio.sleep(min(2 ** attempt, 30))
else:
raise last Prevention
- Match the testnet flag to the environment your API keys belong to before starting the node
- Verify the API key has futures enabled and the system clock is NTP-synced (skew breaks signatures)
- Check egress to fstream.binance.com:443 (wss) from the runtime host — containers and CI often block it
- Log the wrapped {e:?} line — it distinguishes DNS/TLS failures from Binance handshake rejections
When it happens
Trigger: Engine connect with the Binance Futures data client while: the host (fstream.binance.com / testnet stream.binancefuture.com) is unreachable or DNS fails; a corporate firewall blocks outbound wss; the client IP is in a region Binance blocks for futures; an authenticated handshake fails (invalid API key/secret, key without futures permission, clock skew breaking signature); the `testnet` flag does not match the configured keys.
Common situations: US-based developer hitting Binance global futures endpoints (geo-blocked); testnet flag flipped but production keys kept; keys created for spot only; running in Docker/CI without network egress; transient Binance WebSocket outage or maintenance.
Related errors
- failed to connect Binance Futures public WebSocket: {e}
- failed to connect Binance Futures private WebSocket
- failed to connect Binance Spot public JSON WebSocket: {e}
- WS modify order failed: {e}
- failed to connect Binance Spot SBE WebSocket: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/00a7569718cfb4b2.
Report an issue: GitHub.