{"record":{"id":"2d2c3fe6e627a5e4","repo":"jdx/mise","slug":"could-not-get-mtime-for-watch-file","errorCode":null,"errorMessage":"could not get mtime for watch file: {}","messagePattern":"could not get mtime for watch file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/toolset/env_cache.rs","lineNumber":81,"sourceCode":"    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            }\n        } else {\n            bail!(\"could not get mtime for watch file: {}\", path.display());\n        }\n    }\n    Ok(())\n}\n\n/// Represents the cached environment data\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub(crate) struct CachedEnv {\n    /// Cached environment variables\n    pub env: BTreeMap<String, String>,\n    /// Variables explicitly removed by env directives\n    #[serde(default)]\n    pub env_remove: BTreeSet<String>,\n    /// User-configured paths from env._.path directives\n    pub user_paths: Vec<PathBuf>,\n    /// Tool paths from installations\n    pub tool_paths: Vec<PathBuf>,\n    /// Time when the cache was created","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/toolset/env_cache.rs#L63-L99","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Re-run the command — the transient race usually resolves and the cache is rebuilt","Check filesystem permissions allowing stat on the watched files","Ensure no other process deletes/replaces the watched config files while mise runs","Clear the cache (`mise cache clear`) to force a clean rebuild"],"exampleFix":"// before: another job deletes .env mid-run\n// after: serialize jobs or watch a stable file\nmise run dev   # retry, cache regenerated","handlingStrategy":"retry","validationCode":"// ensure files are stable before loading cache\nfor (const f of watchFiles) { try { fs.statSync(f); } catch { await waitForFile(f); } }","typeGuard":"const statable = (f) => { try { fs.statSync(f); return true; } catch { return false; } };","tryCatchPattern":"try { loadEnvCache() } catch (e) { if (String(e).includes('could not get mtime')) { await sleep(50); loadEnvCache(); } else { throw e; } }","preventionTips":["Don't delete or swap watched files while mise runs","Avoid symlink churn on watched config files","Fix permissions so stat works on watched files","Retry on transient stat failures"],"tags":["cache","race-condition","stat"],"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-14T05:17:10.506Z"}