{"record":{"id":"e45dd08828667d07","repo":"jdx/mise","slug":"task-cache-store-version-mismatch-local-version","errorCode":null,"errorMessage":"task cache store version mismatch: local version {}, remote version {}","messagePattern":"task cache store version mismatch: local version (.+?), remote version (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/task_cache_store.rs","lineNumber":185,"sourceCode":"    }\n    fn touch(&self, key: &str);\n}\n\npub(crate) struct CompositeTaskCacheStore {\n    local: Arc<dyn TaskCacheStore>,\n    remote: Arc<dyn TaskCacheStore>,\n    remote_mode: CacheRemoteMode,\n    remote_read_locks: Mutex<HashMap<String, Weak<tokio::sync::Mutex<()>>>>,\n}\n\nimpl CompositeTaskCacheStore {\n    pub(crate) fn new(\n        local: Arc<dyn TaskCacheStore>,\n        remote: Arc<dyn TaskCacheStore>,\n        remote_mode: CacheRemoteMode,\n    ) -> Result<Self> {\n        if local.version() != remote.version() {\n            bail!(\n                \"task cache store version mismatch: local version {}, remote version {}\",\n                local.version(),\n                remote.version()\n            );\n        }\n        Ok(Self {\n            local,\n            remote,\n            remote_mode,\n            remote_read_locks: Mutex::new(HashMap::new()),\n        })\n    }\n\n    fn remote_read_lock(&self, key: &str) -> Arc<tokio::sync::Mutex<()>> {\n        let mut locks = self.remote_read_locks.lock().unwrap();\n        locks.retain(|_, lock| lock.strong_count() > 0);\n        if let Some(lock) = locks.get(key).and_then(Weak::upgrade) {\n            return lock;","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/task/task_cache_store.rs#L167-L203","documentation":"CompositeTaskCacheStore layers a local and a remote store; at construction it asserts both report the same store version because their on-disk formats must agree for entries to be exchanged. A mismatch means the local cache directory and the remote store were created by different format generations.","triggerScenarios":"CompositeTaskCacheStore::new runs with local.version() != remote.version() — typically a local task-artifacts dir (or remote store) written by a newer/older mise than the currently running one.","commonSituations":"mise upgraded on one machine but not another while sharing cache state; switching between stable and prerelease builds; leftover cache dirs from a previous format version.","solutions":["Upgrade (or pin) all machines and CI jobs that share the cache to the same mise version","Clear the stale store: rm -rf ~/.cache/mise/task-artifacts and the matching remote prefix so the current version recreates it","Set task.cache_dir explicitly if you must run parallel caches for different mise versions"],"exampleFix":"# before: CI on 2025.12, laptop on 2026.1, shared remote cache\n# after: pin the same version everywhere\n# .mise.toml\n[tools]\nmise = '2026.1.6'","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// rebuild stores from scratch on version mismatch\nmatch CompositeTaskCacheStore::new(local, remote, mode) {\n    Ok(store) => store,\n    Err(e) if e.to_string().contains(\"task cache store version mismatch\") => {\n        reset_task_cache_dirs();\n        CompositeTaskCacheStore::new(recreate_local_store()?, remote, mode)?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Upgrade all machines sharing a cache at the same time","Set task.cache_dir per mise version if mixed versions are unavoidable","Clear task-artifacts after upgrades rather than carrying old formats forward"],"tags":["mise","task-cache","version","remote-cache"],"backgroundTag":"version-mismatch","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}