cjpais/Handy · error · anyhow::Error

Failed to verify download for model

Error message

Failed to verify download for model {}: {}. Please retry.

What it means

Raised when computing the SHA256 of a downloaded model fails outright (compute_sha256 returns Err), as opposed to computing successfully but mismatching. The cause is an I/O error while reading the file — typically the file vanished, is locked, or the disk failed mid-read. Like the mismatch case, the file is deleted before the error is returned.

Solutions

  1. Retry the download — the code already removed the unreadable file.
  2. Check free disk space; large models need headroom for both the file and temp writes.
  3. Move the models directory off cloud-synced/network storage — sync agents lock or swap files during hashing.
  4. If it persists, check filesystem permissions and disk health (dmesg/Event Viewer for I/O errors).
Defensive patterns

Strategy: retry

Try / catch

match manager.download_model(model_id, None).await {
    Ok(_) => Ok(()),
    Err(e) if e.to_string().contains("Failed to verify download") => {
        // I/O-level verify failure; file removed, safe to retry once
        tokio::time::sleep(std::time::Duration::from_secs(2)).await;
        manager.download_model(model_id, None).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: File::open(path) or a chunk read inside compute_sha256 fails: the partial file was deleted by another process, the disk filled or disconnected, or filesystem permissions changed between download completion and verification.

Common situations: External cleanup tools or a second app instance touching the models directory; disk-full on the same volume that just hosted a multi-GB download; network drives/cloud-sync folders (Dropbox/OneDrive) evicting or locking the file mid-hash; failing sectors on large files.

Related errors


AI-assisted analysis of cjpais/Handy@c89b7bf389 (2026-08-17). Data as JSON: /api/errors/33182402c4f1cc78. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/managers/model/download.rs:78

        match Self::compute_sha256(path) {
            Ok(actual) if actual == expected => {
                info!("SHA256 verified for model {}", model_id);
                Ok(())
            }
            Ok(actual) => {
                warn!(
                    "SHA256 mismatch for model {}: expected {}, got {}",
                    model_id, expected, actual
                );
                let _ = fs::remove_file(path);
                Err(anyhow::anyhow!(
                    "Download verification failed for model {}: file is corrupt. Please retry.",
                    model_id
                ))
            }
            Err(e) => {
                let _ = fs::remove_file(path);
                Err(anyhow::anyhow!(
                    "Failed to verify download for model {}: {}. Please retry.",
                    model_id,
                    e
                ))
            }
        }
    }

    /// Computes the SHA256 hex digest of a file, reading in 64KB chunks to handle large models.
    fn compute_sha256(path: &Path) -> Result<String> {
        let mut file = File::open(path)?;
        let mut hasher = Sha256::new();
        let mut buffer = [0u8; 65536];
        loop {
            let n = file.read(&mut buffer)?;
            if n == 0 {
                break;
            }

View on GitHub (pinned to c89b7bf389)