{"record":{"id":"c86f5d0c975e8a55","repo":"tonhowtf/omniget","slug":"connect-timeout","errorCode":null,"errorMessage":"connect timeout","messagePattern":"connect timeout","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/http_fetcher.rs","lineNumber":964,"sourceCode":"    let end = seg.end_ceiling.load(Ordering::Relaxed);\n    let already = seg.downloaded.load(Ordering::Relaxed);\n    if begin + already > end {\n        return Ok(());\n    }\n    let range_start = begin + already;\n\n    let mut req = client.get(url);\n    if let Some(h) = headers {\n        req = req.headers(headers_without_range(h));\n    }\n    req = req.header(\n        reqwest::header::RANGE,\n        format!(\"bytes={}-{}\", range_start, end),\n    );\n\n    let resp = tokio::time::timeout(cfg.connect_timeout, req.send())\n        .await\n        .map_err(|_| anyhow!(\"connect timeout\"))??;\n\n    let status = resp.status();\n    if status != reqwest::StatusCode::PARTIAL_CONTENT {\n        if status.is_success() {\n            return Err(anyhow!(\"server did not honor Range (HTTP 200)\"));\n        }\n        return Err(anyhow!(\"HTTP {}\", status));\n    }\n\n    // A 206 alone is not proof the server gave us the slice we asked for. If it\n    // answers a different offset and we write the body at ours anyway, the file\n    // still ends up the right size and is silently corrupt — the one failure\n    // mode a segmented download cannot detect later.\n    if let Some(start) = content_range_start(resp.headers()) {\n        if start != range_start {\n            return Err(anyhow!(\n                \"server answered range at byte {} but {} was requested\",\n                start,","sourceCodeStart":946,"sourceCodeEnd":982,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/http_fetcher.rs#L946-L982","documentation":"download_segment sends its ranged GET (bytes=start-end) bounded by tokio::time::timeout(cfg.connect_timeout). A timeout elapsed produces this error via map_err before the reqwest error is propagated with `?`. It means the segment worker could not obtain a response within the configured connect_timeout, so the segment fails and the worker records the error and retries.","triggerScenarios":"A segment's req.send() exceeds cfg.connect_timeout — slow host, packets silently dropped, or connect_timeout configured too low for the link — inside worker_loop's segment download.","commonSituations":"Oversubscribed parallel segment downloads saturating the local link, servers that per-connection throttle, firewalls dropping mid-download connections, or connect_timeout set to a few hundred milliseconds.","solutions":["Increase cfg.connect_timeout in the fetcher configuration.","Reduce the number of parallel segments/worker tasks to avoid self-inflicted saturation.","Retry the download — worker_loop's retry logic may succeed on a fresh connection.","Verify host reachability with `curl -m <t> -r 0-1024 <url>` to reproduce the stall independently."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pick a sane connect_timeout relative to a measured RTT\nlet rtt = measure_rtt(url.host_str()?)?;\nlet cfg = FetcherConfig { connect_timeout: Duration::from_millis((rtt * 20).max(3_000)), ..Default::default() };","typeGuard":null,"tryCatchPattern":"match download(...).await {\n    Err(e) if e.to_string() == \"connect timeout\" => {\n        // worker already retries; at the top level, retry the whole download with fewer segments\n    }\n    other => { other?; }\n}","preventionTips":["Do not set connect_timeout below ~1–3 s for production targets.","Limit parallel segments so the client does not saturate its own uplink.","Enable the worker retry path and cap retries with backoff.","Prefer IPv4 or fix broken IPv6 routes when connects black-hole."],"tags":["network","timeout","download","segment"],"backgroundTag":"request-timeout","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}