cjpais/Handy · error · anyhow::Error
download incomplete: expected {} bytes, got {}
Error message
download incomplete: expected {} bytes, got {} What it means
The byte stream ended cleanly (Ok(None) from the stream) before the expected number of bytes arrived: the final on-disk length differs from known_total. An early close is treated as a truncated transfer; the partial is removed because a short file has no resume value against a mismatching server. The catalog-hash verification after this check is what makes mirror fallbacks trustworthy.
Source
Thrown at src-tauri/src/managers/model/download.rs:368
));
}
}
file.write_all(&chunk)?;
downloaded += chunk.len() as u64;
if last_emit.elapsed() >= throttle {
emit_progress(downloaded);
last_emit = Instant::now();
}
}
file.flush()?;
drop(file);
emit_progress(downloaded);
if let Some(expected) = known_total {
let actual = partial_path.metadata()?.len();
if actual != expected {
let _ = fs::remove_file(partial_path);
return Err(anyhow::anyhow!(
"download incomplete: expected {} bytes, got {}",
expected,
actual
));
}
}
// The catalog hash is the trust anchor: for a mirror (an untrusted
// host) this verification is what makes the fallback safe at all.
Self::verify_file_with_events(model_id, partial_path, expected_sha256, emit).await?;
Ok(HttpDownloadOutcome::Completed)
}
}
#[cfg(test)]
mod tests;
View on GitHub (pinned to 98a4d80cce)
Solutions
- Retry — the partial is already deleted, so the next attempt is a clean full download
- Check for proxy/VPN/AV interference with large streaming responses
- Confirm the server serves the whole file: curl -o /dev/null -w '%{size_download}' <url>
- Move to a more reliable source (official HF) for multi-GB models
Defensive patterns
Strategy: retry
Try / catch
match downloader.download_http_resumable(...).await {
Ok(outcome) => Ok(outcome),
Err(e) if e.to_string().starts_with("download incomplete") => {
// partial removed; a retry is a clean full download
downloader.download_http_resumable(...).await
}
Err(e) => Err(e),
} Prevention
- Retry truncation failures automatically — they are overwhelmingly transient
- Check for middleboxes (AV, proxies) when truncation recurs on one network only
- Cross-check a suspect server with curl -o /dev/null -w '%{size_download}'
When it happens
Trigger: Server closes early while Content-Length promised more bytes; proxy or CDN truncation; a connection reset surfaced as clean EOF.
Common situations: Flaky networks dropping the connection mid-body; servers under load closing streams; antivirus or middleboxes cutting large streaming responses.
Related errors
- transfer stalled: no progress for {}s
- {:?}
- Hugging Face download failed after {} attempt(s): {}
- Download failed from Hugging Face ({}) and {} mirror(s)
- no response within {}s from {}
AI-assisted analysis of cjpais/Handy@98a4d80cce (2026-08-16).
Data as JSON: /api/errors/f6557ba08d2c6cc8.
Report an issue: GitHub.