{"record":{"id":"a3f52ff99f9b4d9c","repo":"nautechsystems/nautilus_trader","slug":"failed-to-terminate-polymarket-data-tasks-e","errorCode":null,"errorMessage":"Failed to terminate Polymarket data tasks: {e}","messagePattern":"Failed to terminate Polymarket data tasks: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/data/lifecycle.rs","lineNumber":426,"sourceCode":"            }\n        };\n        self.tasks\n            .spawn(future)\n            .map_err(|e| anyhow::anyhow!(\"failed to register Polymarket resolve poll: {e}\"))?;\n        Ok(())\n    }\n\n    pub(super) async fn await_tasks_with_timeout(\n        &self,\n        timeout: tokio::time::Duration,\n    ) -> anyhow::Result<()> {\n        self.tasks.begin_shutdown();\n        let graceful_timeout = (timeout / 2).min(TASK_GRACEFUL_SHUTDOWN_TIMEOUT);\n        let abort_timeout = timeout.saturating_sub(graceful_timeout);\n        self.tasks\n            .finish_shutdown(graceful_timeout, abort_timeout)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to terminate Polymarket data tasks: {e}\"))?;\n        Ok(())\n    }\n\n    pub(super) fn start_client(&mut self) {\n        log::info!(\"Starting Polymarket data client: {}\", self.client_id);\n        self.ensure_position_event_subscription();\n    }\n\n    pub(super) fn stop_client(&mut self) {\n        log::info!(\"Stopping Polymarket data client: {}\", self.client_id);\n        self.tasks.begin_shutdown();\n        self.ws_client.begin_shutdown();\n        self.rtds_feed.begin_shutdown();\n        self.is_connected\n            .store(false, std::sync::atomic::Ordering::Relaxed);\n        self.clear_position_event_subscription();\n    }\n","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/data/lifecycle.rs#L408-L444","documentation":"Raised by await_tasks_with_timeout when tasks.finish_shutdown(graceful_timeout, abort_timeout) fails to cleanly terminate all Polymarket data tasks within the computed graceful/abort windows during disconnect. Some data task (WS handler, instrument refresh, resolve poll) did not finish or could not be aborted as expected.","triggerScenarios":"Calling disconnect()/disconnect_client while a background task is stuck (e.g. blocking HTTP call in resolve poll or a wedged WS read) beyond half of the given timeout or TASK_GRACEFUL_SHUTDOWN_TIMEOUT, so finish_shutdown reports failure.","commonSituations":"Unresponsive network stalls in the resolve-poll HTTP client; instrument refresh blocked on a slow Gamma API call; very short user-supplied timeout values making graceful+abort windows too tight.","solutions":["Increase the timeout passed to disconnect() so graceful/abort windows are sufficient","Check network reachability of Polymarket Gamma/WS endpoints that tasks may be blocked on","Upgrade/patch if a task ignores cancellation tokens; ensure tasks honor the cancellation token","Recreate the client if its task group is wedged; start_generation() runs on next connect"],"exampleFix":"// before\nclient.disconnect().await?; // tiny default timeout\n// after\nclient.disconnect_with_timeout(Duration::from_secs(30)).await?;","handlingStrategy":"try-catch","validationCode":"// pick a generous disconnect timeout up front\nlet timeout = Duration::from_secs(30); // not milliseconds\nassert!(timeout > Duration::from_secs(5));","typeGuard":null,"tryCatchPattern":"if let Err(e) = client.disconnect_with_timeout(Duration::from_secs(30)).await {\n    log::error!(\"task termination incomplete: {e}; recreating client\");\n    client = build_client(cfg)?; // wedged group: rebuild\n}","preventionTips":["Pass a disconnect timeout large enough for HTTP-bound tasks (resolve poll) to observe cancellation","Ensure tasks' network calls use timeouts so they cannot hang indefinitely","Monitor endpoint latency to Polymarket Gamma API; slow endpoints lengthen shutdown","On repeated shutdown timeouts, recreate the client instead of reusing the task group"],"tags":["rust","tokio","shutdown-timeout","polymarket"],"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"}