jdx/mise · error
no watch could be installed for the tracked set
Error message
no watch could be installed for the tracked set
What it means
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.
Source
Thrown at src/system/history/watch/runtime.rs:1442
Err(err) => {
let message = format!(
"cannot watch {}: {err}; reconciliation still saves it",
display_path(&anchor.path)
);
capture.health.watcher.degraded.push(message.clone());
capture.out.emit(
"degraded",
&message,
json!({ "path": display_path(&anchor.path), "message": err.to_string() }),
);
}
}
}
// nothing watched while something should be: no event would ever
// arrive, so the caller stops (and the service restarts it) instead of
// running blind until a reconciliation that may be disabled
if current.is_empty() && !wanted.is_empty() {
bail!("no watch could be installed for the tracked set");
}
capture.anchor_ids = current
.iter()
.filter_map(|anchor| {
file_id::get_file_id(&anchor.path)
.ok()
.map(|id| (anchor.path.clone(), id))
})
.collect();
Ok(current)
}
fn anchor_replaced(
ids: &std::collections::BTreeMap<PathBuf, file_id::FileId>,
path: &Path,
) -> bool {
ids.get(path)
.is_some_and(|before| file_id::get_file_id(path).ok().as_ref() != Some(before))View on GitHub (pinned to afd2eddd3a)
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.
Example fix
// before: every root unwatchable, `current` empty // after: shrink tracked set and raise limits, then retry mise history untrack ~/huge-vendored-tree sudo sysctl -w fs.inotify.max_user_watches=524288
Defensive patterns
Strategy: retry
Validate before calling
// ensure at least one tracked root is watchable before enabling the watcher
for root in &tracked_roots {
if !root.exists() || is_unwatchable_fs(root) {
eprintln!("root {:?} cannot be watched", root);
}
} Try / catch
match result {
Err(e) if e.to_string().contains("no watch could be installed") => {
eprintln!("retry after raising limits / fixing roots; rely on reconciliation until then");
schedule_reconciliation_retry();
}
other => other?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- cannot watch {}: the system's watch limit is reached (on Lin
- remote action output tree is too large
- task action manifest contains too many predictions
- rustc output is not a regular file: {}
- failed to create file symlink: {err}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/c255edeb9f682d5f.
Report an issue: GitHub.