{"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/533346cc374382b41ec5ff70536252b2e96e725c/src/task/task_cache_store.rs#L167-L203","documentation":"The hybrid local+remote task cache store compares the format versions reported by both underlying stores in its constructor and refuses to operate if they differ. Mixing a store implementation writing an incompatible cache format would corrupt reads/writes, so the mismatch is a hard constructor error.","triggerScenarios":"Constructing a hybrid TaskCacheStore::new (e.g. during a task run configured with a remote cache) where local.version() != remote.version() — typically after a mise format bump with mismatched binaries/versions on either side.","commonSituations":"Remote cache service or proxy speaking an older/newer cache format than the local client; rolling upgrades across CI workers sharing a remote cache; misconfigured custom store plugin.","solutions":["Upgrade both ends (local mise and remote store) to the same cache format version","Temporarily disable the remote cache (unset the remote cache config) until versions are aligned","Purge remote entries from the old format after upgrading"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before wiring the hybrid store\nif local.version() != remote.version() {\n    eprintln!(\"remote cache format mismatch; disabling remote cache\");\n}","typeGuard":null,"tryCatchPattern":"match TaskCacheStore::new(local, remote, mode) {\n    Err(e) if e.to_string().contains(\"version mismatch\") => {\n        TaskCacheStore::local_only(local) // degrade gracefully\n    }\n    r => r?,\n}","preventionTips":["Deploy local and remote cache components together in lockstep","Check store version compatibility in CI before enabling remote caching","Pin the remote cache service version in infrastructure config"],"tags":["remote-cache","versioning","configuration"],"backgroundTag":"incompatible-source-type","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}