{"record":{"id":"33182402c4f1cc78","repo":"cjpais/Handy","slug":"failed-to-verify-download-for-model-please","errorCode":null,"errorMessage":"Failed to verify download for model {}: {}. Please retry.","messagePattern":"Failed to verify download for model (.+?): (.+?)\\. Please retry\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/model/download.rs","lineNumber":78,"sourceCode":"        match Self::compute_sha256(path) {\n            Ok(actual) if actual == expected => {\n                info!(\"SHA256 verified for model {}\", model_id);\n                Ok(())\n            }\n            Ok(actual) => {\n                warn!(\n                    \"SHA256 mismatch for model {}: expected {}, got {}\",\n                    model_id, expected, actual\n                );\n                let _ = fs::remove_file(path);\n                Err(anyhow::anyhow!(\n                    \"Download verification failed for model {}: file is corrupt. Please retry.\",\n                    model_id\n                ))\n            }\n            Err(e) => {\n                let _ = fs::remove_file(path);\n                Err(anyhow::anyhow!(\n                    \"Failed to verify download for model {}: {}. Please retry.\",\n                    model_id,\n                    e\n                ))\n            }\n        }\n    }\n\n    /// Computes the SHA256 hex digest of a file, reading in 64KB chunks to handle large models.\n    fn compute_sha256(path: &Path) -> Result<String> {\n        let mut file = File::open(path)?;\n        let mut hasher = Sha256::new();\n        let mut buffer = [0u8; 65536];\n        loop {\n            let n = file.read(&mut buffer)?;\n            if n == 0 {\n                break;\n            }","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/cjpais/Handy/blob/98a4d80cce8ad41efec2a419b59d9e81229a35d7/src-tauri/src/managers/model/download.rs#L60-L96","documentation":"The SHA256 computation itself failed with an I/O error before producing a digest; the inner error text is embedded in the message. The downloader treats an unverifiable file as untrustworthy: it deletes the file and asks for a retry. This is a local read failure, not a content mismatch.","triggerScenarios":"The downloaded file was locked or removed by another process (antivirus, backup agent, indexer) while hashing; disk full or failing sectors; permissions on models_dir changed between write and verify.","commonSituations":"Windows Defender or other AV scanning large GGUF downloads and locking them; aggressive backup software; models dir on an ejected or dying external drive.","solutions":["Retry the download","Exclude the app's models directory from antivirus/backup real-time scanning","Free disk space and run a filesystem check","Ensure the process still has read permission on models_dir and the partial file"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match downloader.download_http_resumable(...).await {\n    Ok(outcome) => Ok(outcome),\n    Err(e) if e.to_string().contains(\"Failed to verify download\") => {\n        // local I/O failure during hashing (AV lock, disk issue): retry after a pause\n        tokio::time::sleep(Duration::from_secs(2)).await;\n        downloader.download_http_resumable(...).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Exclude the models directory from real-time antivirus and backup scanning","Keep free disk headroom several times the model size for write-then-verify","Check dmesg/system logs for disk errors when this recurs"],"tags":["sha256","io-error","antivirus","download"],"backgroundTag":"checksum-verification-failed","analyzedSha":"98a4d80cce8ad41efec2a419b59d9e81229a35d7","analyzedAt":"2026-08-16T20:58:09.966Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}