{"record":{"id":"7db18e3fbe5e8668","repo":"cjpais/Handy","slug":"transfer-stalled-no-progress-for-s","errorCode":null,"errorMessage":"transfer stalled: no progress for {}s","messagePattern":"transfer stalled: no progress for (.+?)s","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"src-tauri/src/managers/model.rs","lineNumber":1997,"sourceCode":"                        Err(_) => Err(hf_hub::api::tokio::ApiError::Cancelled),\n                    }\n                }\n            };\n            watchdog.abort();\n\n            match result {\n                Ok(_) => break None,\n                Err(hf_hub::api::tokio::ApiError::Cancelled) if cancel_token.is_cancelled() => {\n                    // User cancelled. hf-hub leaves the partially downloaded\n                    // `.sync.part` in the shared cache, so a later attempt resumes\n                    // instead of restarting. The guard resets is_downloading and\n                    // drops the token; `cancel_download` already emitted\n                    // `model-download-cancelled`.\n                    info!(\"HF download cancelled for: {}\", model_id);\n                    return Ok(());\n                }\n                Err(hf_hub::api::tokio::ApiError::Cancelled) => {\n                    let err = anyhow::anyhow!(\n                        \"transfer stalled: no progress for {}s\",\n                        DOWNLOAD_STALL_TIMEOUT.as_secs()\n                    );\n                    // A parallel attempt may be what wedged the network. Give\n                    // the connection pool a brief pause, then retry once using\n                    // the known-compatible single-stream path. A sequential\n                    // stall already cost DOWNLOAD_STALL_TIMEOUT, so further\n                    // retries would likely just repeat it — use the mirror.\n                    if stream_count == 1 || attempt >= ATTEMPT_STREAMS.len() {\n                        break Some(err);\n                    }\n                    let delay = Duration::from_secs(1_u64 << attempt);\n                    warn!(\n                        \"HF download attempt {}/{} stalled for {} using {} concurrent stream(s); retrying with {} stream(s) in {}s\",\n                        attempt,\n                        ATTEMPT_STREAMS.len(),\n                        model_id,\n                        stream_count,","sourceCodeStart":1979,"sourceCodeEnd":2015,"githubUrl":"https://github.com/cjpais/Handy/blob/98a4d80cce8ad41efec2a419b59d9e81229a35d7/src-tauri/src/managers/model.rs#L1979-L2015","documentation":"The download watchdog cancelled the hf-hub attempt because no transfer progress occurred for DOWNLOAD_STALL_TIMEOUT (60 s) — hf-hub has no internal timeouts, so a wedged connection would otherwise hang forever. The code distinguishes this from a user cancel by checking cancel_token afterwards; this branch is the watchdog path. It is recoverable by design: the loop retries with fewer concurrent streams or falls back to a mirror.","triggerScenarios":"Connection silently drops mid-stream (NAT/VPN idle timeout, captive portal re-auth, switching networks); server or CDN stops sending bytes but keeps the socket open; a throttling proxy that freezes > 60 s. Occurs only during multi-stream or single-stream HF downloads of model files.","commonSituations":"Hotel/coffee-shop Wi-Fi with flaky NAT; VPN reconnects mid-download; corporate proxies that stall large Range-request transfers; long model downloads (hundreds of MB to GB) that outlive flaky paths.","solutions":["Let the built-in retry ladder run — it drops from 4 concurrent streams to 1 with exponential backoff, then mirrors","Stabilize the network (disable VPN, switch to wired/another network) before retrying","If stalls repeat at the same byte offset, the resume .sync.part may be wedged server-side — cancel and restart the download once","Check for bandwidth throttling or proxy interference on Range requests"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// the loop already handles this: verify cancel_token first, then retry with fewer streams or break to mirrors\nErr(hf_hub::api::tokio::ApiError::Cancelled) if !cancel_token.is_cancelled() => {\n    warn!(\"stall watchdog fired; retrying single-stream or falling back to mirror\");\n}","preventionTips":["Keep DOWNLOAD_STALL_TIMEOUT >= worst-case expected inter-chunk latency on slow links (currently 60 s)","Prefer stable networks for multi-GB model downloads; the watchdog cannot fix a dead path, only detect it","Leave the resume .sync.part intact on cancel — later attempts continue instead of restarting"],"tags":["network","hf-hub","timeout","download","watchdog","retry"],"backgroundTag":"download-stalled","analyzedSha":"98a4d80cce8ad41efec2a419b59d9e81229a35d7","analyzedAt":"2026-08-16T20:58:09.966Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}