{"record":{"id":"2e31155536852ffe","repo":"jdx/mise","slug":"cached-description-failed-digest-verification","errorCode":null,"errorMessage":"cached {description} failed digest verification","messagePattern":"cached (.+?) failed digest verification","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/cache/rustc.rs","lineNumber":529,"sourceCode":"\nfn read_canonical_blob<T>(path: &Path, digest: &CacheDigest, description: &str) -> Result<T>\nwhere\n    T: DeserializeOwned + Serialize,\n{\n    let bytes = read_verified_blob(path, digest, description)?;\n    let value = serde_json::from_slice(&bytes)\n        .wrap_err_with(|| format!(\"cached {description} is not valid JSON\"))?;\n    if canonical_json(&value)? != bytes {\n        bail!(\"cached {description} is not canonical JSON\");\n    }\n    Ok(value)\n}\n\nfn read_verified_blob(path: &Path, digest: &CacheDigest, description: &str) -> Result<Vec<u8>> {\n    let mut bytes = Vec::new();\n    std::fs::File::open(path)?.read_to_end(&mut bytes)?;\n    if !digest.matches_bytes(&bytes)? {\n        bail!(\"cached {description} failed digest verification\");\n    }\n    Ok(bytes)\n}\n\nfn validated_outputs(\n    directory: CacheDirectory,\n    outputs: &RustcOutputs,\n) -> Result<Vec<(CacheFileNode, PathBuf)>> {\n    if directory.version != 1 || !directory.directories.is_empty() || !directory.symlinks.is_empty()\n    {\n        bail!(\"cached rustc output directory has unsupported entries\");\n    }\n    let mut expected = outputs\n        .files\n        .iter()\n        .chain(std::iter::once(&outputs.dep_info))\n        .map(|path| {\n            let name = path","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/cache/rustc.rs#L511-L547","documentation":"read_verified_blob() re-hashes a cached blob with blake3 and compares against the digest recorded in the action manifest (src/cache/rustc.rs:525-531). A mismatch means the file content changed after it was stored: silent corruption (bit rot, truncated write), external modification, or a tampered cache. The entry is rejected and the shim falls back to a real compile, so correctness is preserved — only the cache hit is lost.","triggerScenarios":"restore_result reading the action descriptor (src/cache/rustc.rs:306), the metadata/output-root blobs, the stdout/stderr blobs (src/cache/rustc.rs:334-335), or a staged output file whose content no longer hashes to its recorded digest: bit flips on disk, partial writes from a crashed session, or files rewritten by backup/sync/antivirus software.","commonSituations":"Cloud-sync or backup tools rewriting files inside the cache dir; a failing disk; a cache copied between machines with a lossy transfer; another process writing into the CAS.","solutions":["Delete the affected cache directory — corrupted blobs cannot be repaired, only regenerated by recompiling or re-fetched from a healthy remote","Exclude the mise cache directory from sync, backup, and antivirus scanning","If failures recur, check filesystem/disk health (dmesg, smartctl) — repeated digest failures are an early corruption signal","With a remote cache configured, a later clean run re-uploads valid blobs"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"fn blob_ok(path: &Path, digest: &CacheDigest) -> bool {\n    std::fs::read(path)\n        .map(|bytes| digest.matches_bytes(&bytes).unwrap_or(false))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"Mirror the shim: on any integrity failure, drop the cached entry and recompile — `if !blob_ok(&path, &digest) { /* delete entry, run rustc */ }`. Never attempt partial restores from a blob that failed verification.","preventionTips":["Keep the cache on local disk, not network or cloud-synced filesystems","Exclude the cache directory from antivirus, backup, and indexing scans","Treat repeated 'failed digest verification' warnings as a hardware diagnostic trigger"],"tags":["rust","cache","blake3","integrity","corruption"],"backgroundTag":"checksum-verification-failed","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}