{"record":{"id":"c255edeb9f682d5f","repo":"jdx/mise","slug":"no-watch-could-be-installed-for-the-tracked-set","errorCode":null,"errorMessage":"no watch could be installed for the tracked set","messagePattern":"no watch could be installed for the tracked set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/watch/runtime.rs","lineNumber":1442,"sourceCode":"            Err(err) => {\n                let message = format!(\n                    \"cannot watch {}: {err}; reconciliation still saves it\",\n                    display_path(&anchor.path)\n                );\n                capture.health.watcher.degraded.push(message.clone());\n                capture.out.emit(\n                    \"degraded\",\n                    &message,\n                    json!({ \"path\": display_path(&anchor.path), \"message\": err.to_string() }),\n                );\n            }\n        }\n    }\n    // nothing watched while something should be: no event would ever\n    // arrive, so the caller stops (and the service restarts it) instead of\n    // running blind until a reconciliation that may be disabled\n    if current.is_empty() && !wanted.is_empty() {\n        bail!(\"no watch could be installed for the tracked set\");\n    }\n    capture.anchor_ids = current\n        .iter()\n        .filter_map(|anchor| {\n            file_id::get_file_id(&anchor.path)\n                .ok()\n                .map(|id| (anchor.path.clone(), id))\n        })\n        .collect();\n    Ok(current)\n}\n\nfn anchor_replaced(\n    ids: &std::collections::BTreeMap<PathBuf, file_id::FileId>,\n    path: &Path,\n) -> bool {\n    ids.get(path)\n        .is_some_and(|before| file_id::get_file_id(path).ok().as_ref() != Some(before))","sourceCodeStart":1424,"sourceCodeEnd":1460,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/watch/runtime.rs#L1424-L1460","documentation":"After attempting to install watches for all wanted anchors, the runtime found that zero watches could be installed even though the tracked set is non-empty. Since no event would ever arrive, the caller stops and the service restarts reconciliation instead of running blind until some possibly-disabled reconciliation pass.","triggerScenarios":"Calling run/reinstall when every debouncer.watch() call for the tracked roots fails (e.g. all roots hit MaxFilesWatch, or roots have disappeared/unreadable), leaving `current` empty while `wanted` is non-empty.","commonSituations":"System-wide watch exhaustion combined with large tracked sets; tracked directories deleted or permission-restricted after enrollment; containers where inotify is unavailable or its limit is 0.","solutions":["Raise the OS watch limit (Linux: fs.inotify.max_user_watches; macOS: check kern.maxfiles / limits).","Verify each tracked root still exists and is readable; untrack roots that were deleted or moved.","Check filesystem support — watches fail on some network filesystems (NFS) or pseudo-filesystems; untrack those roots.","Restart the history service after fixing limits so it retries watch installation."],"exampleFix":"// before: every root unwatchable, `current` empty\n// after: shrink tracked set and raise limits, then retry\nmise history untrack ~/huge-vendored-tree\nsudo sysctl -w fs.inotify.max_user_watches=524288","handlingStrategy":"retry","validationCode":"// ensure at least one tracked root is watchable before enabling the watcher\nfor root in &tracked_roots {\n    if !root.exists() || is_unwatchable_fs(root) {\n        eprintln!(\"root {:?} cannot be watched\", root);\n    }\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"no watch could be installed\") => {\n        eprintln!(\"retry after raising limits / fixing roots; rely on reconciliation until then\");\n        schedule_reconciliation_retry();\n    }\n    other => other?,\n}","preventionTips":["Keep the tracked set small and rooted on local filesystems","Untrack roots that were deleted or moved","Verify inotify works in your container/runtime before enabling watching","Rely on periodic reconciliation as a safety net; watch failures then degrade gracefully"],"tags":["filesystem","file-watching","inotify","resource-limit"],"backgroundTag":"resource-not-found","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"}