{"record":{"id":"49a1f3e7ad2d162a","repo":"nautechsystems/nautilus_trader","slug":"reconnection-timed-out-after-s-49a1f3","errorCode":null,"errorMessage":"reconnection timed out after {}s","messagePattern":"reconnection timed out after (.+?)s","errorType":"exception","errorClass":"TransportError","httpStatus":null,"severity":"error","filePath":"crates/network/src/websocket/client.rs","lineNumber":1329,"sourceCode":"\n        if ConnectionMode::from_atomic(&self.connection_mode).is_disconnect() {\n            log::debug!(\"Reconnect aborted during connection rate-limit wait\");\n            return Ok(ReconnectOutcome::Aborted);\n        }\n\n        // Bound only connection establishment; the swap below must run to completion\n        let (new_writer, reader) = dst::time::timeout(\n            self.connect_timeout,\n            Box::pin(Self::connect_with_server(\n                &self.config.url,\n                self.reconnect_headers.snapshot(),\n                self.config.backend,\n                self.config.proxy_url.as_deref(),\n            )),\n        )\n        .await\n        .map_err(|_| {\n            TransportError::Io(std::io::Error::new(\n                std::io::ErrorKind::TimedOut,\n                format!(\n                    \"reconnection timed out after {}s\",\n                    self.connect_timeout.as_secs_f64()\n                ),\n            ))\n        })??;\n\n        if ConnectionMode::from_atomic(&self.connection_mode).is_disconnect() {\n            log::debug!(\"Reconnect aborted mid-flight (after connect)\");\n            return Ok(ReconnectOutcome::Aborted);\n        }\n\n        // Use a oneshot channel to synchronize the writer swap before transitioning\n        // back to ACTIVE. Buffered messages stay in the writer task and replay later.\n        let (tx, rx) = tokio::sync::oneshot::channel();\n        if let Err(e) = self.writer_tx.send(WriterCommand::Update(new_writer, tx)) {\n            log::error!(\"{e}\");","sourceCodeStart":1311,"sourceCodeEnd":1347,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/websocket/client.rs#L1311-L1347","documentation":"During reconnection, the client awaits the new connection with a future bounded by the configured connect_timeout. If the underlying connect (including backend/proxy setup) does not finish within that window, the retry is abandoned and this TimedOut TransportError is returned to the reconnect caller. It indicates the peer, DNS, proxy, or network path is too slow or unreachable for the configured budget.","triggerScenarios":"Calling reconnect (via reconnect_with_outcome) while the remote host is unreachable or slow; connect_timeout too small for slow networks or proxied backends; server accepting TCP but never completing the WebSocket handshake within the budget.","commonSituations":"Network outages or flaky Wi-Fi during a trading session; DNS resolution stalls; misconfigured proxy_url adding latency; backend service degraded; connect_timeout set optimistically low (e.g. 5s) for cross-region links.","solutions":["Increase connect_timeout in the WebSocketClient config to a realistic value for your network path","Verify the WebSocket endpoint URL/DNS and any proxy_url are correct and reachable (curl/telnet the host:port)","Check server-side logs for handshake stalls or overloaded accept queues","Wrap reconnect in an outer retry loop with backoff so a single timeout does not kill the session permanently"],"exampleFix":"// before\nWebSocketClientConfig::builder().connect_timeout(Duration::from_secs(5))\n// after\nWebSocketClientConfig::builder().connect_timeout(Duration::from_secs(30))","handlingStrategy":"retry","validationCode":"// Pre-check reachability before reconnect\nif std::net::TcpStream::connect_timeout(&addr, Duration::from_secs(3)).is_err() {\n    // delay reconnect until network is back\n}","typeGuard":"fn is_reconnect_timeout(e: &TransportError) -> bool {\n    matches!(e, TransportError::Io(io) if io.kind() == std::io::ErrorKind::TimedOut)\n}","tryCatchPattern":"match client.reconnect().await {\n    Err(e) if is_reconnect_timeout(&e) => backoff.wait_and_retry(),\n    Err(e) => return Err(e),\n    Ok(()) => {}\n}","preventionTips":["Set connect_timeout generously for worst-case network latency","Add an outer retry loop with exponential backoff around reconnect","Monitor endpoint reachability and pause reconnects during known outages"],"tags":["network","websocket","timeout","reconnect","rust"],"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"}