{"record":{"id":"f869702d4b5d0c9b","repo":"nautechsystems/nautilus_trader","slug":"failed-to-terminate-hyperliquid-data-session-tasks","errorCode":null,"errorMessage":"Failed to terminate Hyperliquid data session tasks: {e}","messagePattern":"Failed to terminate Hyperliquid data session tasks: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/adapters/hyperliquid/src/data.rs","lineNumber":270,"sourceCode":"        Ok(())\n    }\n\n    async fn await_pending_tasks(&self) -> anyhow::Result<()> {\n        self.pending_tasks.begin_shutdown();\n        self.pending_tasks\n            .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to terminate Hyperliquid data tasks: {e}\"))?;\n        Ok(())\n    }\n\n    async fn await_session_tasks(&self) -> anyhow::Result<()> {\n        self.session_tasks.begin_shutdown();\n        self.session_tasks\n            .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))\n            .await\n            .map_err(|e| {\n                anyhow::anyhow!(\"Failed to terminate Hyperliquid data session tasks: {e}\")\n            })?;\n        Ok(())\n    }\n\n    fn clear_stream_health(&self) {\n        self.stream_health.lock().clear();\n    }\n\n    fn register_stream_health(&self, channel: MarketDataChannel, instrument_id: InstrumentId) {\n        if !self.stream_health_monitor_enabled() {\n            return;\n        }\n\n        self.stream_health\n            .lock()\n            .subscribe(channel, instrument_id, Instant::now());\n    }\n","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/data.rs#L252-L288","documentation":"This error wraps a failure from the data client's session task shutdown in `await_session_tasks` (crates/adapters/hyperliquid/src/data.rs:270). During teardown the client asks its managed WebSocket session tasks to stop, giving them 1 second to begin shutdown and 2 seconds to finish; if any task refuses to end in time or panics, `finish_shutdown` returns an error which is re-raised with this message. It indicates stale Hyperliquid market-data connections/tasks could not be cleanly terminated.","triggerScenarios":"Calling teardown_partial_connect (via DataClient disconnect) when a spawned session task is blocked (e.g. stuck in a network read that ignores the cancellation token), hung, or takes longer than the 1s/2s shutdown timeouts.","commonSituations":"Network partitions or proxies holding the WebSocket open; a WS task blocked on a slow recv; system suspend/resume leaving sockets half-dead; calling disconnect while a large subscribe/reconnect loop is in flight.","solutions":["Retry the disconnect after a short pause; the tasks usually finish or are abandoned by the timeout.","Check network/firewall conditions that keep the WebSocket from closing promptly.","If it reproduces, inspect custom session task code or proxy settings that block socket close; restart the process/node to clear stuck tasks.","Ensure you are on a recent adapter version where cancellation tokens are applied to all session tasks."],"exampleFix":"// before\nclient.disconnect().await.expect(\"disconnect must succeed\");\n// after\nif let Err(e) = client.disconnect().await {\n    tracing::warn!(\"hyperliquid data teardown issue: {e:#}\"); // tolerate timeout during shutdown\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust\nmatch client.disconnect().await {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"Failed to terminate\") => {\n        tracing::warn!(\"data session tasks did not shut down in time: {e:#}\");\n        // safe to proceed/reconnect; tasks are force-aborted by timeout\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always await disconnect fully before dropping or reconnecting the client.","Avoid network conditions (VPNs, aggressive proxies) that stall WebSocket close handshakes.","Monitor for repeated teardown timeouts; they signal hung tasks that need investigation."],"tags":["websocket","shutdown","timeout","async","hyperliquid"],"backgroundTag":"request-timeout","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"}