{"record":{"id":"3b9697946728c419","repo":"nautechsystems/nautilus_trader","slug":"shutdown-errors-joined-with-3b9697","errorCode":null,"errorMessage":"{shutdown_errors joined with \"; \"}","messagePattern":"\\{shutdown_errors joined with \"; \"\\}","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/execution.rs","lineNumber":634,"sourceCode":"        self.begin_session_shutdown();\n        self.pending_tasks.begin_shutdown();\n\n        if let Err(e) = self.ws_client.disconnect().await {\n            self.shutdown_errors\n                .push(format!(\"Hyperliquid WebSocket shutdown failed: {e}\"));\n        }\n\n        if let Err(e) = self.await_session_tasks().await {\n            self.shutdown_errors.push(e.to_string());\n        }\n\n        if let Err(e) = self.await_pending_tasks().await {\n            self.shutdown_errors.push(e.to_string());\n        }\n        self.core.set_disconnected();\n\n        if !self.shutdown_errors.is_empty() {\n            anyhow::bail!(std::mem::take(&mut self.shutdown_errors).join(\"; \"));\n        }\n        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","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/execution.rs#L616-L652","documentation":"During teardown (partial-connect cleanup or disconnect), the client shuts down background tasks and collects any failures into shutdown_errors. If any teardown step failed, the accumulated messages are joined with \"; \" and returned as a single aggregated error.","triggerScenarios":"Calling disconnect (or failing a connect and running teardown_partial_connect) while one or more shutdown steps fail — e.g. await_pending_tasks reports a task error, WebSocket close fails, or command-sender shutdown fails; all messages are joined and raised together.","commonSituations":"Disconnecting while subscriptions/tasks are still in flight and erroring during cancellation; a partially initialized client being torn down after a failed connect; network errors during WebSocket close.","solutions":["Read the joined message to identify which specific shutdown step(s) failed and address those underlying errors first.","Retry disconnect() — shutdown_errors is taken (cleared) on this error, so a fresh attempt starts clean.","Ensure tasks are cancelled and data streams are closed before dropping the client (unsubscribe/cancel outstanding requests).","Upgrade the adapter if the underlying failure looks like a teardown race/bug."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = client.disconnect().await {\n    log::error!(\"disconnect reported shutdown failures: {e}\");\n    // retry once; shutdown_errors was cleared by the failed attempt\n    client.disconnect().await?;\n}","preventionTips":["Cancel outstanding tasks/subscriptions before disconnecting","Ensure clean network state (no in-flight requests) at teardown","Log the joined message to identify the failing shutdown step"],"tags":["rust","hyperliquid","shutdown","teardown","aggregated-error"],"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-14T05:17:10.506Z"}