{"record":{"id":"c5f561bf398bcd4e","repo":"nautechsystems/nautilus_trader","slug":"no-websocket-client-available","errorCode":null,"errorMessage":"No WebSocket client available","messagePattern":"No WebSocket client available","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/websocket/handler.rs","lineNumber":352,"sourceCode":"                    || {\n                        let payload = payload.clone();\n                        async move {\n                            client\n                                .send_text(payload, Some(std::slice::from_ref(&rate_key)))\n                                .await\n                                .map_err(|e| {\n                                    HyperliquidWsError::ClientError(format!(\"Send failed: {e}\"))\n                                })\n                        }\n                    },\n                    should_retry_hyperliquid_error,\n                    |e| create_hyperliquid_timeout_error(e.to_string()),\n                )\n                .execute()\n                .await\n                .map_err(|e| anyhow::anyhow!(\"{e}\"))\n        } else {\n            Err(anyhow::anyhow!(\"No WebSocket client available\"))\n        }\n    }\n\n    pub(super) async fn next(&mut self) -> Option<NautilusWsMessage> {\n        if let Some(msg) = self.message_buffer.pop_front() {\n            return Some(msg);\n        }\n\n        loop {\n            if self.raw_closed && self.cmd_rx.is_empty() {\n                log::debug!(\"Handler shutting down: input stream closed\");\n                return None;\n            }\n\n            tokio::select! {\n                cmd = self.cmd_rx.recv(), if !self.cmd_closed => {\n                    let Some(cmd) = cmd else {\n                        self.cmd_closed = true;","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/websocket/handler.rs#L334-L370","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nhandler.handle_command(cmd).await?;\n// after\nassert!(handler.is_connected(), \"handler has no ws client\");\nhandler.handle_command(cmd).await?;","handlingStrategy":"type-guard","validationCode":"// Rust\nfn handler_ready(handler: &HyperliquidWsHandler) -> bool {\n    handler.has_client()\n}","typeGuard":"// check before sending commands\nif !handler.has_client() {\n    return Err(anyhow::anyhow!(\"handler not connected yet\"));\n}","tryCatchPattern":"if let Err(e) = handler.handle_command(cmd).await {\n    if e.to_string().contains(\"No WebSocket client\") {\n        wait_until_connected().await?;\n        handler.handle_command(cmd).await?;\n    } else { return Err(e); }\n}","preventionTips":["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"],"tags":["websocket","lifecycle","not-initialized","hyperliquid"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}