{"record":{"id":"0420b3aab5d456ca","repo":"nautechsystems/nautilus_trader","slug":"failed-to-start-rtds-message-loop-e-startup-ro","errorCode":null,"errorMessage":"Failed to start RTDS message loop: {e}; startup rollback failed: {shutdown_error}","messagePattern":"Failed to start RTDS message loop: (.+?); startup rollback failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/rtds.rs","lineNumber":970,"sourceCode":"        if let Err(e) = spawn_result {\n            ws.disconnect().await;\n            self.clear_ws_if_current(&ws);\n            let shutdown_error = match finish_task(\n                &mut message_slot,\n                Duration::ZERO,\n                Duration::from_secs(2),\n            )\n            .await\n            {\n                Some(TaskJoinOutcome::Failed(error)) => {\n                    Some(format!(\"message loop task failed: {error}\"))\n                }\n                Some(TaskJoinOutcome::Incomplete) => {\n                    Some(\"message loop task did not stop after abort\".to_string())\n                }\n                None | Some(TaskJoinOutcome::Completed(()) | TaskJoinOutcome::Aborted) => None,\n            };\n            anyhow::bail!(match shutdown_error {\n                Some(shutdown_error) => format!(\n                    \"Failed to start RTDS message loop: {e}; startup rollback failed: \\\n                     {shutdown_error}\"\n                ),\n                None => format!(\"Failed to start RTDS message loop: {e}\"),\n            });\n        }\n\n        Ok(true)\n    }\n\n    fn is_generation_open(&self, generation: u64) -> bool {\n        let current_generation = self.inner.shutdown_generation.lock();\n        *current_generation == generation && !self.inner.closing.load(Ordering::Acquire)\n    }\n\n    fn websocket_config(&self) -> WebSocketConfig {\n        WebSocketConfig {","sourceCodeStart":952,"sourceCodeEnd":988,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/rtds.rs#L952-L988","documentation":"Raised when the RTDS message loop fails to start AND the startup rollback (aborting/joining the just-started task) itself fails to complete cleanly — e.g. the aborted task did not stop within the 2-second join window ('message loop task did not stop after abort'). The combined message reports both the original start error and the rollback failure.","triggerScenarios":"spawn_result.is_err() (e.g. the task panics immediately or the spawn hook fails) and finish_task on the aborted message slot returns Incomplete within the 2-second join window.","commonSituations":"Message-loop task panicking at startup plus a hung join; the tokio runtime shutting down so the aborted task is never polled to completion; a blocked cleanup path in the message loop.","solutions":["Inspect the inner error first — fix the root cause of the message-loop start failure (usually a panic or invalid initial state).","Ensure the runtime stays alive until teardown joins complete; do not drop the runtime mid-abort.","Harden the message loop against early panics by validating state before spawning.","Check for blocking calls in the abort/join path that prevent the task from stopping."],"exampleFix":"// before\nanyhow::bail!(format!(\"Failed to start RTDS message loop: {e}\")); // hides rollback outcome\n// after\nif let Some(rb) = shutdown_error {\n    log::error!(\"RTDS startup rollback failed: {rb}\");\n}\nanyhow::bail!(\"Failed to start RTDS message loop: {e}\");","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = feed.connect().await {\n    let msg = format!(\"{e:#}\");\n    if msg.contains(\"Failed to start RTDS message loop\") {\n        log::error!(\"RTDS startup failure (check rollback note): {msg}\");\n        // recreate feed; state may be partially torn down\n    }\n    return Err(e);\n}","preventionTips":["Fix the underlying message-loop start error first; the rollback failure is secondary.","Keep the tokio runtime alive until feed teardown completes so aborts can join.","Avoid panics in the message-loop entry path by validating state before spawn.","Monitor for this error as a signal of both a startup and a teardown bug."],"tags":["task-spawn","startup-failure","rollback","tokio","polymarket"],"backgroundTag":"internal-invariant-violation","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"}