jdx/mise · error · eyre::Report
cached {description} failed digest verification
Error message
cached {description} failed digest verification What it means
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.
Source
Thrown at src/cache/rustc.rs:529
fn read_canonical_blob<T>(path: &Path, digest: &CacheDigest, description: &str) -> Result<T>
where
T: DeserializeOwned + Serialize,
{
let bytes = read_verified_blob(path, digest, description)?;
let value = serde_json::from_slice(&bytes)
.wrap_err_with(|| format!("cached {description} is not valid JSON"))?;
if canonical_json(&value)? != bytes {
bail!("cached {description} is not canonical JSON");
}
Ok(value)
}
fn read_verified_blob(path: &Path, digest: &CacheDigest, description: &str) -> Result<Vec<u8>> {
let mut bytes = Vec::new();
std::fs::File::open(path)?.read_to_end(&mut bytes)?;
if !digest.matches_bytes(&bytes)? {
bail!("cached {description} failed digest verification");
}
Ok(bytes)
}
fn validated_outputs(
directory: CacheDirectory,
outputs: &RustcOutputs,
) -> Result<Vec<(CacheFileNode, PathBuf)>> {
if directory.version != 1 || !directory.directories.is_empty() || !directory.symlinks.is_empty()
{
bail!("cached rustc output directory has unsupported entries");
}
let mut expected = outputs
.files
.iter()
.chain(std::iter::once(&outputs.dep_info))
.map(|path| {
let name = pathView on GitHub (pinned to 6f52dcdf99)
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
Defensive patterns
Strategy: fallback
Validate before calling
fn blob_ok(path: &Path, digest: &CacheDigest) -> bool {
std::fs::read(path)
.map(|bytes| digest.matches_bytes(&bytes).unwrap_or(false))
.unwrap_or(false)
} Try / catch
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. Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- remote cache blob failed digest verification
- cached {description} is not canonical JSON
- cached rustc output set does not match the invocation
- cached rustc output set is incomplete
- remote cache blob pack content length metadata mismatch: exp
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/2e31155536852ffe.
Report an issue: GitHub.