{"record":{"id":"0d75aa27f541b548","repo":"nautechsystems/nautilus_trader","slug":"hyperliquid-websocket-handler-failed-error","errorCode":null,"errorMessage":"Hyperliquid WebSocket handler failed: {error}","messagePattern":"Hyperliquid WebSocket handler failed: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/websocket/client.rs","lineNumber":582,"sourceCode":"                \"Failed to send disconnect command (handler may already be shut down): {e}\"\n            );\n        }\n\n        if self.task_handle.is_empty() {\n            log::debug!(\"No task handle to await\");\n        } else {\n            log::debug!(\"Waiting for task handle to complete\");\n\n            if let Some(outcome) = self\n                .task_handle\n                .finish(Duration::from_secs(2), Duration::from_secs(2))\n                .await\n            {\n                match outcome {\n                    TaskJoinOutcome::Completed(()) | TaskJoinOutcome::Aborted => {}\n                    TaskJoinOutcome::Failed(error) => {\n                        self.release_limit_reservations();\n                        anyhow::bail!(\"Hyperliquid WebSocket handler failed: {error}\");\n                    }\n                    TaskJoinOutcome::Incomplete => {\n                        self.release_limit_reservations();\n                        anyhow::bail!(\"Hyperliquid WebSocket handler did not stop after abort\");\n                    }\n                }\n            }\n        }\n        self.release_limit_reservations();\n        log::debug!(\"Disconnected\");\n        Ok(())\n    }\n\n    /// Requests a full transport reconnect.\n    ///\n    /// Transitions the connection from `Active` to `Reconnect`; the network\n    /// layer re-establishes the socket with backoff and the handler replays all\n    /// active subscriptions once reconnected. Returns `false` when the","sourceCodeStart":564,"sourceCodeEnd":600,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/websocket/client.rs#L564-L600","documentation":"Raised in disconnect_locked after the client aborts the WebSocket handler task and joins it: if the join yields TaskJoinOutcome::Failed(error), the handler task terminated with an error rather than completing or aborting cleanly. The client releases its rate-limit reservations and propagates the handler's underlying error wrapped in this message, so the real cause is in the inner error text.","triggerScenarios":"Calling disconnect() (or the reconnect path in connect_locked) while the handler task has already failed with an error: the WebSocket connection errored, a command failed, or the handler panicked and the join captured the payload.","commonSituations":"Network drop or exchange-side WebSocket close killing the handler just before disconnect; panics inside message-handling code (unwrap on unexpected payloads); calling disconnect() concurrently with a failing connection.","solutions":["Read the inner {error} in the message, which names the real handler failure, and fix that root cause first.","Inspect logs for panics or WebSocket errors in the handler task and harden that path (avoid unwrap on exchange payloads).","Recreate the client after this error; the handler is dead and reservations were released.","During best-effort teardown, treat this error as non-fatal since the connection was already broken."],"exampleFix":"// before: propagate handler failure during shutdown teardown / client.disconnect().await?; / // after: best-effort teardown / if let Err(e) = client.disconnect().await { log::warn!(\"disconnect after handler failure (ignoring): {e}\"); }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = client.disconnect().await { if e.to_string().contains(\"handler failed\") { log::warn!(\"handler already failed during disconnect: {e}\"); client = HyperliquidWebSocketClient::new(url, ...); } }","preventionTips":["Fix the inner handler error first; this message only wraps it.","Harden handler code against panics (no unwrap on exchange payloads).","Make best-effort disconnects tolerant: log and rebuild rather than fail teardown.","Watch for network drops that kill the handler before you call disconnect()."],"tags":["websocket","async","task-panic","shutdown","tokio"],"backgroundTag":"handler-task-join-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}