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

  1. Nothing to fix if the edit was intended — mise simply recomputes the env; re-run the command
  2. 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
  3. Clear caches (`mise cache clear`) if you suspect bad cache state
  4. 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

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


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