jdx/mise · error

task cache store version mismatch: local version

Error message

task cache store version mismatch: local version {}, remote version {}

What it means

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.

Solutions

  1. Upgrade both ends (local mise and remote store) to the same cache format version
  2. Temporarily disable the remote cache (unset the remote cache config) until versions are aligned
  3. Purge remote entries from the old format after upgrading
Defensive patterns

Strategy: validation

Validate before calling

// before wiring the hybrid store
if local.version() != remote.version() {
    eprintln!("remote cache format mismatch; disabling remote cache");
}

Try / catch

match TaskCacheStore::new(local, remote, mode) {
    Err(e) if e.to_string().contains("version mismatch") => {
        TaskCacheStore::local_only(local) // degrade gracefully
    }
    r => r?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/e45dd08828667d07. Report an issue: GitHub.

Appendix: source

Thrown at src/task/task_cache_store.rs:185

    }
    fn touch(&self, key: &str);
}

pub(crate) struct CompositeTaskCacheStore {
    local: Arc<dyn TaskCacheStore>,
    remote: Arc<dyn TaskCacheStore>,
    remote_mode: CacheRemoteMode,
    remote_read_locks: Mutex<HashMap<String, Weak<tokio::sync::Mutex<()>>>>,
}

impl CompositeTaskCacheStore {
    pub(crate) fn new(
        local: Arc<dyn TaskCacheStore>,
        remote: Arc<dyn TaskCacheStore>,
        remote_mode: CacheRemoteMode,
    ) -> Result<Self> {
        if local.version() != remote.version() {
            bail!(
                "task cache store version mismatch: local version {}, remote version {}",
                local.version(),
                remote.version()
            );
        }
        Ok(Self {
            local,
            remote,
            remote_mode,
            remote_read_locks: Mutex::new(HashMap::new()),
        })
    }

    fn remote_read_lock(&self, key: &str) -> Arc<tokio::sync::Mutex<()>> {
        let mut locks = self.remote_read_locks.lock().unwrap();
        locks.retain(|_, lock| lock.strong_count() > 0);
        if let Some(lock) = locks.get(key).and_then(Weak::upgrade) {
            return lock;

View on GitHub (pinned to 533346cc37)