jdx/mise · info
watch file mtime changed: {} (expected: {}, current: {})
Error message
watch file mtime changed: {} (expected: {}, current: {}) What it means
mise caches environment output keyed on the mtimes of watched files. If validation finds a file whose current mtime differs from the mtime recorded in the cache, the cached env may be stale, so mise rejects the cache and recomputes.
Source
Thrown at src/toolset/env_cache.rs:73
.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
);
}
} else {
bail!("could not get mtime for watch file: {}", path.display());
}
}
Ok(())
}
/// Represents the cached environment data
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct CachedEnv {
/// Cached environment variables
pub env: BTreeMap<String, String>,View on GitHub (pinned to afd2eddd3a)
Solutions
- Nothing to fix if the edit was intended — mise simply recomputes the env; re-run the command
- If the file's mtime changes spuriously (e.g. a tool rewrites it on every run), stop that tool from rewriting the file or write only when content changes
- Clear caches (`mise cache clear`) if you suspect bad cache state
- Avoid `touch`ing config files in scripts when contents don't change
Example fix
// before: script rewrites file every run, invalidating cache echo "KEY=val" > .env // after: only write when changed [ -f .env ] || echo "KEY=val" > .env
Defensive patterns
Strategy: retry
Validate before calling
// stat files yourself and compare to cached mtimes to predict invalidation const changed = watchFiles.some(f => fs.statSync(f).mtimeMs !== cachedMtime(f));
Try / catch
try { loadEnvCache() } catch (e) { if (String(e).includes('mtime changed')) { /* expected: recompute env */ recomputeEnv(); } else { throw e; } } Prevention
- Avoid touching/rewriting config files whose content didn't change
- Make generators write files only when content differs
- Exclude volatile files from watch lists
- Be aware git operations update mtimes and will invalidate cache (harmless)
When it happens
Trigger: env_cache::load compares get_file_mtime(path) against expected_mtime and they differ — any write, touch, or regeneration of a watched file after the cache was created.
Common situations: Editing .env or mise.toml between runs; CI/cron regenerating env files; tools rewriting config files (changing content or just mtime) even when contents are identical; git operations that update file timestamps.
Related errors
- watch file count mismatch
- watch file no longer exists: {}
- action prediction payload is too large
- task action manifest has an invalid identity
- task action manifest contains duplicate predictions
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/e00065aaecb99772.
Report an issue: GitHub.