jdx/mise · error

watch file count mismatch

Error message

watch file count mismatch

What it means

env_cache::load calls validate_watch_files to verify that every watched file recorded when the environment was cached is still present and matches the cached mtime list. Before comparing individual files it asserts the two slices are the same length; if not, the cache data is structurally corrupt or was written by an incompatible version. mise bails so the cache is discarded rather than reused.

Source

Thrown at src/toolset/env_cache.rs:61

        bail!("data too short to contain nonce");
    }

    let nonce =
        Nonce::try_from(&data[..12]).map_err(|e| eyre::eyre!("failed to read nonce: {}", e))?;
    let ciphertext = &data[12..];

    let cipher = ChaCha20Poly1305::new_from_slice(key)
        .map_err(|e| eyre::eyre!("failed to create cipher: {}", e))?;

    let plaintext = cipher
        .decrypt(&nonce, ciphertext)
        .map_err(|e| eyre::eyre!("decryption failed: {}", e))?;
    Ok(plaintext)
}

fn validate_watch_files(watch_files: &[PathBuf], expected_mtimes: &[u64]) -> Result<()> {
    if watch_files.len() != expected_mtimes.len() {
        bail!("watch file count mismatch");
    }
    for (path, expected_mtime) in watch_files.iter().zip(expected_mtimes.iter()) {
        if !path.exists() {
            // mtime=0 means file didn't exist when cached - skip if still doesn't exist
            if *expected_mtime == 0 {
                continue;
            }
            bail!("watch file no longer exists: {}", path.display());
        }
        if let Some(current_mtime) = get_file_mtime(path) {
            if current_mtime != *expected_mtime {
                bail!(
                    "watch file mtime changed: {} (expected: {}, current: {})",
                    path.display(),
                    expected_mtime,
                    current_mtime
                );
            }

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Delete the mise env cache file(s) (or `mise cache clear`) so a fresh cache is written
  2. Re-run the mise command that loaded the env — the cache will be regenerated
  3. Upgrade/downgrade consistently; don't mix cache files from different mise versions
  4. Avoid hand-editing or truncating cache files under the mise cache directory

Example fix

// before (corrupt cache on disk)
mise run dev   # watch file count mismatch
// after
rm -rf ~/.cache/mise/env-cache && mise run dev
Defensive patterns

Strategy: validation

Validate before calling

// check cache sanity before loading
if (watch_files.length !== expected_mtimes.length) {
  clearEnvCache(); // e.g. `mise cache clear`
}

Type guard

const cacheIsConsistent = (c) => Array.isArray(c.watch_files) && Array.isArray(c.expected_mtimes) && c.watch_files.length === c.expected_mtimes.length;

Try / catch

try { loadEnvCache() } catch (e) { if (String(e).includes('watch file count mismatch')) { clearEnvCache(); retry(); } else { throw e; } }

Prevention

When it happens

Trigger: Calling env_cache::load on a cache file where the serialized watch_files and expected_mtimes arrays disagree in length — e.g. a hand-edited, truncated, or corrupted cache file, or a cache written by a different mise version with a different serialization format.

Common situations: Cache corruption after an interrupted write, manual edits to the cache directory, downgrading/upgrading mise across cache format changes, or concurrent mise processes writing the same cache file.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/61e2c5f1c9991a8c. Report an issue: GitHub.