{"record":{"id":"7ea53eb97bb11689","repo":"jdx/mise","slug":"task-cache-artifact-checksum-mismatch","errorCode":null,"errorMessage":"task cache artifact checksum mismatch","messagePattern":"task cache artifact checksum mismatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/task_cache.rs","lineNumber":941,"sourceCode":"        execution_duration_ns: manifest.execution_duration_ns,\n        archive_checksum,\n    };\n    let encoded = serde_json::to_string(&material)?;\n    Ok(format!(\"blake3:{}\", hash::hash_blake3_to_str(&encoded)))\n}\n\nfn verify_artifact_checksum(manifest: &CacheManifest, archive_path: Option<&Path>) -> Result<()> {\n    let Some(expected) = &manifest.artifact_checksum else {\n        return Ok(());\n    };\n    let archive_path = if manifest.roots.is_empty() {\n        None\n    } else {\n        Some(archive_path.ok_or_else(|| eyre!(\"task cache archive is missing\"))?)\n    };\n    let actual = calculate_artifact_checksum(manifest, archive_path)?;\n    if actual != *expected {\n        bail!(\"task cache artifact checksum mismatch\");\n    }\n    Ok(())\n}\n\npub(crate) fn task_cache_entries(task: &Task, root: &Path) -> Result<Vec<TaskCacheEntry>> {\n    Settings::get().ensure_experimental(\"task artifact caching\")?;\n    let cache_dir = task_cache_dir();\n    if !cache_dir.is_dir() {\n        return Ok(Vec::new());\n    }\n    let identity = task_cache_identity(task, root);\n    let current_key = file::read_to_string(task_cache_state_path(task, root))\n        .ok()\n        .map(|key| key.trim().to_string());\n    let mut entries = Vec::new();\n    for entry in fs::read_dir(&cache_dir)? {\n        let entry = entry?;\n        let manifest_path = entry.path();","sourceCodeStart":923,"sourceCodeEnd":959,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/task/task_cache.rs#L923-L959","documentation":"verify_artifact_checksum recomputes the artifact checksum from the manifest roots and the archive and compares it to manifest.artifact_checksum. A mismatch means the archived bytes no longer match what was recorded at save time — corruption, tampering, or a partially overwritten archive — so the cache refuses to restore untrusted content.","triggerScenarios":"Restoring an entry whose archive was modified after save: bit rot, a concurrent writer replacing the artifact, a remote cache proxy serving truncated/mangled bodies, or manual edits inside the cache. The check runs during both restore paths via verify_artifact_checksum(manifest, archive_path).","commonSituations":"Shared remote cache with unreliable storage; NFS muting fsync semantics; two CI jobs racing on the same key; security-sensitive setups where this bail is the tamper alarm.","solutions":["Delete the affected entry (or wipe the cache dir) and re-run to regenerate the artifact","If using a remote store, verify its integrity/headers and check for concurrent writers on the same key","Ensure the cache volume is writable and stable (no disk-full, no flaky mounts)","Treat unexpected checksum failures on a private cache as possible tampering and rotate the cache"],"exampleFix":"# shell\nrm -rf \"${XDG_CACHE_HOME:-$HOME/.cache}/task-artifacts/v2/<entry-dir>\nmise run build","handlingStrategy":"fallback","validationCode":"# recompute and compare if you mirror caches externally\ncd /path/to/extract && find . -type f | sort | xargs sha256sum | sha256sum","typeGuard":null,"tryCatchPattern":"Delete the entry, re-run uncached to regenerate, and if failures repeat on a private single-writer cache, investigate storage/bit-rot; on shared caches, treat as tampering and rotate.","preventionTips":["Serve remote caches over verified TLS with integrity-checked uploads","Prevent concurrent writers on one key","Alert on repeated checksum failures — silent corruption elsewhere may follow"],"tags":["mise","task-cache","caching","integrity","checksum"],"backgroundTag":"cache-checksum-mismatch","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}