{"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":2042,"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":2024,"sourceCodeEnd":2060,"githubUrl":"https://github.com/cjpais/Handy/blob/ba10ce1943ef34e93c09494027fc0b9ced2e8a44/src-tauri/src/managers/model.rs#L2024-L2060","documentation":"This is an internal, recoverable watchdog signal, not a terminal failure: hf-hub has no internal timeouts, so the manager wraps each attempt with a child cancel token that fires when no download progress is observed within DOWNLOAD_STALL_TIMEOUT (60s, model/download.rs:26). The library surfaces the cut connection as ApiError::Cancelled; when the parent (user) token is NOT cancelled, the code maps it to this synthetic stall error. The retry loop then backs off (1s << attempt) and retries with fewer parallel streams, falling back to a mirror after a sequential stall.","triggerScenarios":"A wedged TCP connection (NAT/proxy silently dropping bytes) while downloading with parallel range streams; server-side throttling that halts one stream; laptop sleep/resume mid-download; a flaky VPN or hotspot link that stalls without resetting.","commonSituations":"Unstable Wi-Fi or mobile hotspot; VPN/proxy middleboxes idling out large transfers; HF CDN hiccups under load; machine suspending during a multi-GB model download.","solutions":["On first occurrence, do nothing — the built-in backoff, single-stream retry, and mirror fallback handle it","If stalls recur: switch to a stable network or disable VPN/proxy and retry the download","Retry the same model later — the shared .sync.part cache resumes instead of restarting","As a maintainer: do not add extra retries beyond the schedule; a sequential stall already costs 60s and the code correctly diverts to the mirror instead"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// internal to the manager: map ApiError::Cancelled to stall only when the user didn't cancel\nErr(hf_hub::api::tokio::ApiError::Cancelled) if !cancel_token.is_cancelled() => {\n    // already handled: back off (1s << attempt), reduce streams, or break to mirror fallback\n}","preventionTips":["Trust the built-in ladder: stream-count backoff → single-stream retry → mirror fallback","Keep DOWNLOAD_STALL_TIMEOUT at a value large enough for slow-but-alive links (60s today)","Do not wrap download_model in your own tight retry loop — you would multiply the 60s stall cost"],"tags":["rust","huggingface","download","timeout","watchdog","network"],"backgroundTag":"download-stalled-timeout","analyzedSha":"ba10ce1943ef34e93c09494027fc0b9ced2e8a44","analyzedAt":"2026-08-17T10:29:55.597Z","contentChangedAt":"2026-08-17T10:29:55.597Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}