cjpais/Handy · warning · anyhow::Error
transfer stalled: no progress for
Error message
transfer stalled: no progress for {}s What it means
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.
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
Defensive patterns
Strategy: retry
Try / catch
// internal to the manager: map ApiError::Cancelled to stall only when the user didn't cancel
Err(hf_hub::api::tokio::ApiError::Cancelled) if !cancel_token.is_cancelled() => {
// already handled: back off (1s << attempt), reduce streams, or break to mirror fallback
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Hugging Face download failed after
- Download failed from Hugging Face
- Failed to init Hugging Face API
- no response within s from
- transfer stalled: no data for
AI-assisted analysis of cjpais/Handy@ba10ce1943 (2026-08-17).
Data as JSON: /api/errors/7db18e3fbe5e8668.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/managers/model.rs:2042
Err(_) => Err(hf_hub::api::tokio::ApiError::Cancelled),
}
}
};
watchdog.abort();
match result {
Ok(_) => break None,
Err(hf_hub::api::tokio::ApiError::Cancelled) if cancel_token.is_cancelled() => {
// User cancelled. hf-hub leaves the partially downloaded
// `.sync.part` in the shared cache, so a later attempt resumes
// instead of restarting. The guard resets is_downloading and
// drops the token; `cancel_download` already emitted
// `model-download-cancelled`.
info!("HF download cancelled for: {}", model_id);
return Ok(());
}
Err(hf_hub::api::tokio::ApiError::Cancelled) => {
let err = anyhow::anyhow!(
"transfer stalled: no progress for {}s",
DOWNLOAD_STALL_TIMEOUT.as_secs()
);
// A parallel attempt may be what wedged the network. Give
// the connection pool a brief pause, then retry once using
// the known-compatible single-stream path. A sequential
// stall already cost DOWNLOAD_STALL_TIMEOUT, so further
// retries would likely just repeat it — use the mirror.
if stream_count == 1 || attempt >= ATTEMPT_STREAMS.len() {
break Some(err);
}
let delay = Duration::from_secs(1_u64 << attempt);
warn!(
"HF download attempt {}/{} stalled for {} using {} concurrent stream(s); retrying with {} stream(s) in {}s",
attempt,
ATTEMPT_STREAMS.len(),
model_id,
stream_count,View on GitHub (pinned to ba10ce1943)