nautechsystems/nautilus_trader · error · anyhow::Error
No WebSocket client available
Error message
No WebSocket client available
What it means
send_with_retry returns this error when the handler has no WebSocket client instance to send through — the Option holding the client is None. This happens before a connection is established or after the client was taken/cleared during teardown.
Source
Thrown at crates/adapters/hyperliquid/src/websocket/handler.rs:352
|| {
let payload = payload.clone();
async move {
client
.send_text(payload, Some(std::slice::from_ref(&rate_key)))
.await
.map_err(|e| {
HyperliquidWsError::ClientError(format!("Send failed: {e}"))
})
}
},
should_retry_hyperliquid_error,
|e| create_hyperliquid_timeout_error(e.to_string()),
)
.execute()
.await
.map_err(|e| anyhow::anyhow!("{e}"))
} else {
Err(anyhow::anyhow!("No WebSocket client available"))
}
}
pub(super) async fn next(&mut self) -> Option<NautilusWsMessage> {
if let Some(msg) = self.message_buffer.pop_front() {
return Some(msg);
}
loop {
if self.raw_closed && self.cmd_rx.is_empty() {
log::debug!("Handler shutting down: input stream closed");
return None;
}
tokio::select! {
cmd = self.cmd_rx.recv(), if !self.cmd_closed => {
let Some(cmd) = cmd else {
self.cmd_closed = true;View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure connect() has succeeded before issuing commands
- Wait for connection-established signal before replaying subscriptions
- During reconnect, buffer commands and replay only after the new client is attached
- Treat the error as a lifecycle bug and re-initialize the handler/client pair
Example fix
// before handler.handle_command(cmd).await?; // after assert!(handler.is_connected(), "handler has no ws client"); handler.handle_command(cmd).await?;
Defensive patterns
Strategy: type-guard
Validate before calling
// Rust
fn handler_ready(handler: &HyperliquidWsHandler) -> bool {
handler.has_client()
} Type guard
// check before sending commands
if !handler.has_client() {
return Err(anyhow::anyhow!("handler not connected yet"));
} Try / catch
if let Err(e) = handler.handle_command(cmd).await {
if e.to_string().contains("No WebSocket client") {
wait_until_connected().await?;
handler.handle_command(cmd).await?;
} else { return Err(e); }
} Prevention
- Await the connected event before sending commands
- Do not queue commands to a handler that was never connected
- On reconnect, attach the new client before replaying commands
- Fail fast with a clear lifecycle error in wrappers
When it happens
Trigger: handle_command or replay_subscriptions is called on a handler that has not been given a WebSocket client (pre-connect) or after disconnect/cleanup cleared it. There is no retry possible; it fails fast.
Common situations: Calling subscribe/replay before connect() completes; using the handler after close(); a reconnect cycle where the client was dropped but commands still arrive in the queue.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Failed to start Hyperliquid data session generation: {e}
- Failed to start Hyperliquid data task generation: {e}
- std::mem::take(&mut self.shutdown_errors).join("; ")
- Binance Spot public JSON stream pool is shutting down
- No active WebSocket client
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c5f561bf398bcd4e.
Report an issue: GitHub.