cjpais/Handy · error · anyhow::Error
download incomplete: expected
Error message
download incomplete: expected {} bytes, got {} What it means
Raised after the body stream ends normally but the on-disk file size does not match the expected total — the server closed the connection early without signaling an error. The size check is the last line of defense before hash verification; a short file can never pass the SHA256 gate anyway. The incomplete partial is deleted, so a retry restarts from zero (a too-short stream taints the whole append).
Solutions
- Retry the download — the incomplete file is already deleted.
- Keep the models directory on local disk, not cloud-synced storage.
- If it fails at the same percentage repeatedly, test the URL with curl to see where the server cuts off; then switch sources.
- Rule out disk-full: the check needs room for the full expected size.
Defensive patterns
Strategy: retry
Try / catch
match manager.download_model(model_id, None).await {
Ok(_) => Ok(()),
Err(e) if e.to_string().contains("download incomplete") => {
// short stream: partial deleted; retry from scratch
manager.download_model(model_id, None).await
}
Err(e) => Err(e),
} Prevention
- Always compare final file size against the expected total before trusting a download (as this code does).
- Store models on local disks, not synced/network volumes that truncate or evict files.
- Keep enough free disk space for the full expected size plus overhead.
- Retry short transfers automatically a bounded number of times before surfacing to the user.
When it happens
Trigger: Server closes the connection mid-body (Content-Length larger than what is sent); proxy cuts the transfer; keep-alive reuse races; cloud-sync folder pinning/unpinning the file as it is written.
Common situations: Flaky connections that drop without RST reaching the client; CDN nodes failing mid-stream; AV quarantining the partial before completion; writing model files into a synced folder.
Related errors
- Complete model file not found
- Download verification failed for model
- Hugging Face download failed after
- Model is currently downloading
- no response within s from
AI-assisted analysis of cjpais/Handy@c89b7bf389 (2026-08-17).
Data as JSON: /api/errors/f6557ba08d2c6cc8.
Report an issue: GitHub.
Appendix: 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 c89b7bf389)