{"record":{"id":"5b3c82c2675790a5","repo":"nautechsystems/nautilus_trader","slug":"connection-timed-out-after-s","errorCode":null,"errorMessage":"connection timed out after {}s","messagePattern":"connection timed out after (.+?)s","errorType":"exception","errorClass":"TransportError::Io(std::io::Error)","httpStatus":null,"severity":"error","filePath":"crates/network/src/websocket/client.rs","lineNumber":420,"sourceCode":"                    rate_limit\n                        .limiter\n                        .await_keys_ready(Some(&rate_limit.keys))\n                        .await;\n                }\n\n                // Bound only the dial: the connection rate-limit wait has its own venue timing\n                dst::time::timeout(\n                    connect_timeout,\n                    Box::pin(Self::connect_with_server(\n                        &config.url,\n                        config.headers.clone(),\n                        config.backend,\n                        config.proxy_url.as_deref(),\n                    )),\n                )\n                .await\n                .unwrap_or_else(|_| {\n                    Err(TransportError::Io(std::io::Error::new(\n                        std::io::ErrorKind::TimedOut,\n                        format!(\n                            \"connection timed out after {}s\",\n                            connect_timeout.as_secs_f64()\n                        ),\n                    )))\n                })\n            })\n        };\n        let classify = |error: &TransportError| {\n            let retryable = is_retryable_initial_connect_error(error);\n            let attempt = attempt.load(Ordering::Relaxed);\n            if retryable && attempt < max_attempts && !cancellation_token.is_cancelled() {\n                log::warn!(\n                    \"WebSocket connection attempt {attempt}/{max_attempts} to {REDACTED} failed: {error}\"\n                );\n            }\n            retryable","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/websocket/client.rs#L402-L438","documentation":"The connection future (using the selected backend and optional proxy) is raced against the configured connect timeout; when the timeout wins, the client returns a `ErrorKind::TimedOut` error with the elapsed seconds, indicating the WebSocket endpoint did not complete the handshake in time.","triggerScenarios":"Calling `connect_url_with_handler` when the remote WebSocket endpoint is unreachable, hangs during TLS/handshake, a configured `proxy_url` is down or slow, or `connect_timeout` is set lower than realistic network latency.","commonSituations":"Data-feed endpoints that silently drop packets, wrong port/host in config, broken proxy configuration, network throttling, or sub-second timeouts used in low-latency setups.","solutions":["Verify the endpoint URL and port are correct and reachable (`curl`/`wscat` to the URL).","Increase `connect_timeout` (e.g. to 10–30s) in the WebSocket config.","If `proxy_url` is set, test the proxy independently; remove or fix it if it is the bottleneck.","Add retry-with-backoff around connect for transient network issues."],"exampleFix":"// before\nlet config = WebSocketConfig { connect_timeout: Duration::from_millis(200), .. };\n// after\nlet config = WebSocketConfig { connect_timeout: Duration::from_secs(20), .. };","handlingStrategy":"retry","validationCode":"// sanity-check endpoint and timeout before connecting\nassert!(url.starts_with(\"wss://\") || url.starts_with(\"ws://\"));\nassert!(config.connect_timeout >= Duration::from_secs(1));","typeGuard":null,"tryCatchPattern":"match connect_url_with_handler(url, handler, config).await {\n    Err(e) if e.to_string().contains(\"connection timed out\") => {\n        tokio::time::sleep(backoff.next()).await;\n        // retry connect\n    }\n    Err(e) => return Err(e),\n    Ok(c) => c,\n}","preventionTips":["Validate the endpoint with a quick manual handshake (wscat/curl) before wiring it up.","Keep connect_timeout well above worst-case TLS handshake time.","Test proxy_url separately; a dead proxy presents exactly as this timeout.","Wrap connects in retry-with-backoff for transient network conditions."],"tags":["websocket","timeout","network","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"}