jdx/mise · error

could not get mtime for watch file: {}

Error message

could not get mtime for watch file: {}

What it means

After confirming a watched file exists, mise tries to read its mtime to compare against the cached value. If get_file_mtime returns None despite path.exists() being true, mise cannot validate the cache entry and bails rather than trusting unverified cached env.

Source

Thrown at src/toolset/env_cache.rs:81

    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>,
    /// Variables explicitly removed by env directives
    #[serde(default)]
    pub env_remove: BTreeSet<String>,
    /// User-configured paths from env._.path directives
    pub user_paths: Vec<PathBuf>,
    /// Tool paths from installations
    pub tool_paths: Vec<PathBuf>,
    /// Time when the cache was created

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Re-run the command — the transient race usually resolves and the cache is rebuilt
  2. Check filesystem permissions allowing stat on the watched files
  3. Ensure no other process deletes/replaces the watched config files while mise runs
  4. Clear the cache (`mise cache clear`) to force a clean rebuild

Example fix

// before: another job deletes .env mid-run
// after: serialize jobs or watch a stable file
mise run dev   # retry, cache regenerated
Defensive patterns

Strategy: retry

Validate before calling

// ensure files are stable before loading cache
for (const f of watchFiles) { try { fs.statSync(f); } catch { await waitForFile(f); } }

Type guard

const statable = (f) => { try { fs.statSync(f); return true; } catch { return false; } };

Try / catch

try { loadEnvCache() } catch (e) { if (String(e).includes('could not get mtime')) { await sleep(50); loadEnvCache(); } else { throw e; } }

Prevention

When it happens

Trigger: env_cache::load validation where path.exists() is true but get_file_mtime(path) yields None — typically a race where the file is deleted between the two calls, or filesystem/stat errors (broken symlink target change, permission issues on stat).

Common situations: Concurrent processes deleting/replacing watched files while mise loads the cache; files swapped with symlinks pointing at a missing target; unusual filesystems or restricted permissions on stat.

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/2d2c3fe6e627a5e4. Report an issue: GitHub.