{"record":{"id":"2ffb388475c91be0","repo":"nautechsystems/nautilus_trader","slug":"polymarket-execution-shutdown-failed","errorCode":null,"errorMessage":"Polymarket execution shutdown failed: {}","messagePattern":"Polymarket execution shutdown failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/execution/lifecycle.rs","lineNumber":439,"sourceCode":"\n        if let Err(e) = self.ws_client.disconnect().await {\n            self.shutdown_errors.push(e.to_string());\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            Ok(())\n        } else {\n            let errors = std::mem::take(&mut self.shutdown_errors);\n            anyhow::bail!(\n                \"Polymarket execution shutdown failed: {}\",\n                errors.join(\"; \")\n            )\n        }\n    }\n\n    pub(super) fn get_neg_risk(&self, instrument_id: &InstrumentId) -> bool {\n        self.neg_risk_index\n            .get_cloned(instrument_id)\n            .unwrap_or(false)\n    }\n\n    pub(super) fn get_neg_risk_from_snapshot(\n        neg_risk_index: &AHashMap<InstrumentId, bool>,\n        instrument_id: &InstrumentId,\n    ) -> bool {\n        neg_risk_index.get(instrument_id).copied().unwrap_or(false)\n    }","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/lifecycle.rs#L421-L457","documentation":"During Polymarket execution client teardown, any error collected while stopping sub-components (streams, websocket, orders cache) is accumulated in shutdown_errors and reported together at the end. teardown_partial_connect returns Ok only when shutdown was fully clean; otherwise it aggregates all shutdown errors into one anyhow error. This ensures a partially failed disconnect is never silently swallowed.","triggerScenarios":"Calling connect_client or disconnect_client when one or more shutdown steps fail (e.g. websocket close fails, stream task join errors), causing shutdown_errors to be non-empty when the final check runs.","commonSituations":"Network already down when disconnecting; Polymarket CLOB/WebSocket endpoints unreachable mid-teardown; reconnect loops where a previous partial connect leaves tasks that fail to stop cleanly; process shutdown racing with active subscriptions.","solutions":["Inspect the joined error list in the message to see which specific shutdown step(s) failed","Verify network connectivity and that the Polymarket endpoints are reachable during disconnect","Check logs for the underlying component errors preceding this aggregate message","Retry disconnect after a short delay; ensure idempotent teardown if errors persist","If it occurs on a stale client, discard the client and build a fresh connection instead of retrying teardown"],"exampleFix":"// before\nmatch client.disconnect().await {\n    Err(e) => log::warn(\"ignored shutdown error: {e}\"),\n    Ok(_) => {},\n}\n// after\nif let Err(e) = client.disconnect().await {\n    log::error!(\"Polymarket execution shutdown failed: {e:#}\");\n    return Err(e); // propagate instead of swallowing, so state isn't assumed clean\n}","handlingStrategy":"try-catch","validationCode":"// Rust: ensure the client is connected and tasks are healthy before disconnect\nif !client.is_connected() {\n    log::warn!(\"client already disconnected; skipping teardown\");\n    return Ok(());\n}","typeGuard":null,"tryCatchPattern":"match client.disconnect().await {\n    Ok(()) => info!(\"shutdown clean\"),\n    Err(e) => {\n        // message contains the joined per-step shutdown errors\n        error!(\"shutdown failed: {e:#}\");\n        // mark state disconnected and rebuild client rather than reusing\n    }\n}","preventionTips":["Make disconnect idempotent and safe to call from multiple code paths","Log each shutdown step's error at its source, not just the aggregate","Avoid tearing down while streams are mid-reconnect","Monitor network health before scheduled shutdowns"],"tags":["rust","shutdown","polymarket","anyhow"],"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"}