{"record":{"id":"cb3dd4868585029c","repo":"nautechsystems/nautilus_trader","slug":"failed-to-terminate-hyperliquid-execution-session","errorCode":null,"errorMessage":"Failed to terminate Hyperliquid execution session tasks: {e}","messagePattern":"Failed to terminate Hyperliquid execution session tasks: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/execution.rs","lineNumber":654,"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 execution 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 execution session tasks: {e}\")\n            })?;\n        Ok(())\n    }\n}\n\n#[async_trait(?Send)]\nimpl ExecutionClient for HyperliquidExecutionClient {\n    fn is_connected(&self) -> bool {\n        self.core.is_connected()\n    }\n\n    fn client_id(&self) -> ClientId {\n        self.core.client_id\n    }\n\n    fn account_id(&self) -> AccountId {\n        self.core.account_id\n    }","sourceCodeStart":636,"sourceCodeEnd":672,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/execution.rs#L636-L672","documentation":"Raised when the Hyperliquid execution client's session-task group (long-lived WebSocket/session loops) cannot be terminated within the shutdown grace and cancel windows during teardown. It wraps the underlying finish_shutdown error from the TaskGroup.","triggerScenarios":"await_session_tasks() is called from teardown_partial_connect() after a failed/partial connect; it errors when session tasks do not stop within Duration::from_secs(1) grace plus Duration::from_secs(2) hard-cancel.","commonSituations":"A session task blocked awaiting a WebSocket read that ignores the shutdown signal; slow network teardown after a partial connect failure; a session task stuck retrying against an unreachable Hyperliquid endpoint.","solutions":["Check that session tasks honor the begin_shutdown signal promptly in their select loops","Retry teardown after a delay, or treat it as non-fatal and log a warning","Inspect the wrapped error to identify which session task stalled","Increase the grace/cancel durations if session loops legitimately need longer to unwind"],"exampleFix":"// before\n.map_err(|e| anyhow::anyhow!(\"Failed to terminate Hyperliquid execution session tasks: {e}\"))?;\n// after\nif let Err(e) = self.session_tasks.finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)).await {\n    log::warn!(\"session tasks did not terminate cleanly: {e}\");\n}","handlingStrategy":"try-catch","validationCode":"if !self.session_tasks.is_open() { self.teardown_partial_connect().await?; }","typeGuard":null,"tryCatchPattern":"match client.await_session_tasks().await { Err(e) => { log::warn!(\"session tasks did not terminate: {e}\"); /* proceed or retry */ } Ok(_) => {} }","preventionTips":["Ensure session loops select on the shutdown signal in every await point","Add timeouts to WS reads so shutdown is observed promptly","Avoid spawning session tasks outside the managed group","Test disconnect/reconnect paths under slow-network conditions"],"tags":["rust","shutdown","task-group","websocket"],"backgroundTag":"request-timeout","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"}