{"record":{"id":"61e2c5f1c9991a8c","repo":"jdx/mise","slug":"watch-file-count-mismatch","errorCode":null,"errorMessage":"watch file count mismatch","messagePattern":"watch file count mismatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/toolset/env_cache.rs","lineNumber":61,"sourceCode":"        bail!(\"data too short to contain nonce\");\n    }\n\n    let nonce =\n        Nonce::try_from(&data[..12]).map_err(|e| eyre::eyre!(\"failed to read nonce: {}\", e))?;\n    let ciphertext = &data[12..];\n\n    let cipher = ChaCha20Poly1305::new_from_slice(key)\n        .map_err(|e| eyre::eyre!(\"failed to create cipher: {}\", e))?;\n\n    let plaintext = cipher\n        .decrypt(&nonce, ciphertext)\n        .map_err(|e| eyre::eyre!(\"decryption failed: {}\", e))?;\n    Ok(plaintext)\n}\n\nfn validate_watch_files(watch_files: &[PathBuf], expected_mtimes: &[u64]) -> Result<()> {\n    if watch_files.len() != expected_mtimes.len() {\n        bail!(\"watch file count mismatch\");\n    }\n    for (path, expected_mtime) in watch_files.iter().zip(expected_mtimes.iter()) {\n        if !path.exists() {\n            // mtime=0 means file didn't exist when cached - skip if still doesn't exist\n            if *expected_mtime == 0 {\n                continue;\n            }\n            bail!(\"watch file no longer exists: {}\", path.display());\n        }\n        if let Some(current_mtime) = get_file_mtime(path) {\n            if current_mtime != *expected_mtime {\n                bail!(\n                    \"watch file mtime changed: {} (expected: {}, current: {})\",\n                    path.display(),\n                    expected_mtime,\n                    current_mtime\n                );\n            }","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/toolset/env_cache.rs#L43-L79","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Delete the mise env cache file(s) (or `mise cache clear`) so a fresh cache is written","Re-run the mise command that loaded the env — the cache will be regenerated","Upgrade/downgrade consistently; don't mix cache files from different mise versions","Avoid hand-editing or truncating cache files under the mise cache directory"],"exampleFix":"// before (corrupt cache on disk)\nmise run dev   # watch file count mismatch\n// after\nrm -rf ~/.cache/mise/env-cache && mise run dev","handlingStrategy":"validation","validationCode":"// check cache sanity before loading\nif (watch_files.length !== expected_mtimes.length) {\n  clearEnvCache(); // e.g. `mise cache clear`\n}","typeGuard":"const cacheIsConsistent = (c) => Array.isArray(c.watch_files) && Array.isArray(c.expected_mtimes) && c.watch_files.length === c.expected_mtimes.length;","tryCatchPattern":"try { loadEnvCache() } catch (e) { if (String(e).includes('watch file count mismatch')) { clearEnvCache(); retry(); } else { throw e; } }","preventionTips":["Don't hand-edit or truncate mise cache files","Keep mise versions consistent across environments sharing a cache","Ensure cache writes complete atomically (mise handles this; don't interrupt writes)","Run `mise cache clear` after abnormal termination"],"tags":["cache","corruption","env"],"backgroundTag":"internal-invariant-violation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}