{"record":{"id":"3bd20898203845b8","repo":"nautechsystems/nautilus_trader","slug":"rtds-connection-was-canceled-by-shutdown","errorCode":null,"errorMessage":"RTDS connection was canceled by shutdown","messagePattern":"RTDS connection was canceled by shutdown","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/adapters/polymarket/src/rtds.rs","lineNumber":876,"sourceCode":"            WebSocketClient::builder()\n                .config(config)\n                .message_handler(handler)\n                .maybe_state_sink(\n                    self.inner\n                        .socket_control\n                        .as_ref()\n                        .map(SocketControl::sink)\n                        .or_else(|| self.inner.socket_sink.clone()),\n                )\n                .connect()\n                .await\n                .context(\"failed to connect Polymarket RTDS WebSocket\")?,\n        );\n\n        if !self.is_generation_open(generation) {\n            ws.notify_closed();\n            ws.disconnect().await;\n            anyhow::bail!(\"RTDS connection was canceled by shutdown\");\n        }\n\n        log::debug!(\"Polymarket RTDS WebSocket connected: {}\", self.inner.url);\n        *self.inner.ws_client.lock() = Some(Arc::clone(&ws));\n\n        // Tokio cancellation is cooperative. Quiesce the previous loop before\n        // activating the replacement so an admitted old-loop tail cannot emit\n        // after newer data from the new connection.\n        let tasks = self\n            .task_slots()\n            .ok_or_else(|| anyhow::anyhow!(\"RTDS task owner was dropped\"))?;\n        let mut message_slot = tasks.message.lock().await;\n        if !self.is_generation_open(generation) {\n            drop(message_slot);\n            ws.notify_closed();\n            ws.disconnect().await;\n            self.clear_ws_if_current(&ws);\n            anyhow::bail!(\"RTDS connection was canceled by shutdown\");","sourceCodeStart":858,"sourceCodeEnd":894,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/rtds.rs#L858-L894","documentation":"Raised when a freshly established RTDS WebSocket connection belongs to a superseded shutdown generation — shutdown was requested while the WebSocket handshake was in flight. The code notifies closed, disconnects the new socket, and bails so the stale connection is never registered. It is a deliberate cancellation guard, not a connection failure.","triggerScenarios":"disconnect/shutdown bumps the generation (or sets closing) while ensure_connected's WebSocket connect is awaiting; the connect completes after the generation check window and is rejected.","commonSituations":"Engine shutdown racing a reconnect loop; test teardown aborting tasks mid-connect; user calling disconnect concurrently with automatic reconnection after a network drop.","solutions":["Avoid racing shutdown with connect: join or abort outstanding connect tasks before calling shutdown.","In callers, treat this error as benign cancellation (log debug; do not retry or alert).","In reconnect loops, check the shutdown flag each iteration before reconnecting.","If it fires without an actual shutdown, verify the generation counter is not being bumped erroneously."],"exampleFix":"// before\nhandle.abort(); // shutdown while connect in flight -> canceled error\nfeed.disconnect().await;\n// after\nfeed.disconnect().await; // cancels/joins in-flight connect cleanly first\nhandle.abort();","handlingStrategy":"retry","validationCode":"if feed.is_shutdown() {\n    log::debug!(\"not reconnecting: feed shut down\");\n    return Ok(());\n}","typeGuard":"fn is_shutdown_cancellation(err: &anyhow::Error) -> bool {\n    err.to_string().contains(\"canceled by shutdown\")\n}","tryCatchPattern":"match feed.ensure_connected().await {\n    Ok(()) => {},\n    Err(e) if is_shutdown_cancellation(&e) => log::debug!(\"reconnect canceled by shutdown\"),\n    Err(e) => return Err(e),\n}","preventionTips":["Stop reconnect loops when shutdown is signaled (select! on a shutdown token).","Abort reconnection tasks before calling disconnect/shutdown.","Filter this error out of retry counters — retrying after shutdown is pointless.","Keep generation checks centralized so the guard stays consistent."],"tags":["websocket","shutdown","race-condition","reconnect","polymarket"],"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"}