{"record":{"id":"4e8d73e385f324ec","repo":"jdx/mise","slug":"task-cache-manifest-does-not-match-cache-key","errorCode":null,"errorMessage":"task cache manifest does not match cache key","messagePattern":"task cache manifest does not match cache key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/task_cache.rs","lineNumber":725,"sourceCode":"        if self.limits.configured()\n            && let Err(err) = enforce_task_cache_limits(&self.cache_dir, self.limits)\n        {\n            warn!(\n                \"failed to enforce task cache limits in {}: {err}\",\n                self.cache_dir.display()\n            );\n        }\n        Ok(())\n    }\n\n    fn entry_lock(&self) -> Result<fslock::LockFile> {\n        task_cache_entry_lock(&self.cache_dir, &self.key)\n    }\n\n    fn read_manifest(&self, contents: &[u8]) -> Result<CacheManifest> {\n        let manifest: CacheManifest = serde_json::from_slice(contents)?;\n        if manifest.format != CACHE_FORMAT_VERSION || manifest.key != self.key {\n            bail!(\"task cache manifest does not match cache key\");\n        }\n        Ok(manifest)\n    }\n}\n\nfn cleanup_abandoned_partial_writes_once(cache_dir: &Path) {\n    if !cache_dir.is_dir() {\n        return;\n    }\n    let should_clean = CLEANED_PARTIAL_CACHE_DIRS\n        .lock()\n        .unwrap_or_else(|err| err.into_inner())\n        .insert(cache_dir.to_path_buf());\n    if should_clean && let Err(err) = cleanup_abandoned_partial_writes(cache_dir) {\n        CLEANED_PARTIAL_CACHE_DIRS\n            .lock()\n            .unwrap_or_else(|err| err.into_inner())\n            .remove(cache_dir);","sourceCodeStart":707,"sourceCodeEnd":743,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/task/task_cache.rs#L707-L743","documentation":"read_manifest deserializes the entry's manifest but then requires manifest.format == CACHE_FORMAT_VERSION (2) and manifest.key == this entry's key. Either mismatch means the manifest does not belong to this entry/format — a stale entry from an older mise, a copied/misplaced manifest, or corruption — so the restore aborts.","triggerScenarios":"Cache entries written by an older mise using format version 1 now read by a version expecting 2; a manifest file moved between entry directories; the entry's key directory renamed so self.key no longer matches the embedded key field.","commonSituations":"Upgrading mise and reusing the old cache dir (the versioned 'v2' path mitigates but remote stores may not); manually pruning or relocating cache entries; sync tools (Dropbox/rsync) mixing manifests across machines with different mise versions.","solutions":["Clear the task cache directory and re-run the task to rebuild entries in the current format","Upgrade any machine still writing the old format so all writers share one mise version","Avoid copying/moving individual entry directories; delete and let mise recreate them","Report a bug if a single fresh mise version reproduces it on a newly written entry"],"exampleFix":"# shell\nrm -rf \"${XDG_CACHE_HOME:-$HOME/.cache}/task-artifacts\"\nmise run build","handlingStrategy":"fallback","validationCode":"mise --version\njq -r '.format, .key' ~/.cache/task-artifacts/v2/*/manifest.json 2>/dev/null | sort -u  # inspect formats present","typeGuard":null,"tryCatchPattern":"On mismatch, delete the stale entry or the whole cache dir and re-run; do not retry unchanged — the format/key will not heal itself.","preventionTips":["Use per-version cache dirs when running multiple mise versions","Don't sync cache dirs between machines with different mise versions","Clear cache after mise upgrades"],"tags":["mise","task-cache","caching","versioning","manifest"],"backgroundTag":"cache-manifest-key-mismatch","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}