jdx/mise · error

cannot watch {}: the system's watch limit is reached (on Lin

Error message

cannot watch {}: the system's watch limit is reached (on Linux raise fs.inotify.max_user_watches)

What it means

When installing watches for tracked roots, the notify debouncer failed with ErrorKind::MaxFilesWatch and there was no fallback anchor already installed, so the runtime cannot receive change events for the path at all and aborts. The kernel's per-user watch limit (inotify watches on Linux) is exhausted.

Source

Thrown at src/system/history/watch/runtime.rs:1408

        if wanted.contains(anchor) {
            current.push(anchor.clone());
        } else if let Err(err) = debouncer.unwatch(&anchor.path) {
            debug!("history watch: unwatch {}: {err}", anchor.path.display());
        }
    }
    for anchor in wanted {
        if current.contains(anchor) {
            continue;
        }
        let mode = match anchor.mode {
            Mode::Recursive => RecursiveMode::Recursive,
            Mode::Flat => RecursiveMode::NonRecursive,
        };
        match debouncer.watch(&anchor.path, mode) {
            Ok(()) => current.push(anchor.clone()),
            Err(err) if matches!(err.kind, notify::ErrorKind::MaxFilesWatch) => {
                if current.is_empty() {
                    bail!(
                        "cannot watch {}: the system's watch limit is reached (on Linux raise fs.inotify.max_user_watches)",
                        display_path(&anchor.path)
                    );
                }
                let message = format!(
                    "cannot watch {}: the system's watch limit is reached; reconciliation still saves it (on Linux raise fs.inotify.max_user_watches)",
                    display_path(&anchor.path)
                );
                capture.health.watcher.degraded.push(message.clone());
                capture.out.emit(
                    "degraded",
                    &message,
                    json!({ "path": display_path(&anchor.path) }),
                );
            }
            Err(err) => {
                let message = format!(
                    "cannot watch {}: {err}; reconciliation still saves it",

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Raise the Linux watch limit: `sudo sysctl fs.inotify.max_user_watches=524288` and persist it in /etc/sysctl.conf or /etc/sysctl.d/.
  2. Reduce the tracked set — untrack very large directories so fewer recursive watches are needed.
  3. Check current consumption with `sysctl fs.inotify.max_user_watches` and `find ~/ tracked-dir | wc -l`; free watches by closing other watchers (editors, file sync tools).
  4. In containers, raise the limit on the host or run with a higher sysctl (e.g. docker run --sysctl fs.inotify.max_user_watches=524288).

Example fix

// before (default limit too small)
$ cat /proc/sys/fs/inotify/max_user_watches
8192
// after
$ echo 'fs.inotify.max_user_watches=524288' | sudo tee /etc/sysctl.d/60-inotify.conf
$ sudo sysctl --system
Defensive patterns

Strategy: fallback

Validate before calling

# check watch headroom before installing watches
sysctl fs.inotify.max_user_watches
find <tracked-root> -type f | wc -l   # rough per-root watch demand

Try / catch

match result {
    Err(e) if e.to_string().contains("watch limit is reached") => {
        eprintln!("raise fs.inotify.max_user_watches or reduce tracked roots");
        // fall back to periodic reconciliation instead of watching
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling run/reinstall when the tracked set requires a new recursive watch on a large tree while the process has hit inotify.max_user_watches (Linux) or the equivalent OS limit; typical when tracking a directory with tens of thousands of files.

Common situations: Linux systems with small fs.inotify.max_user_watches (default 8192) and large node_modules-style trees; containers with low limits; many dev tools (VS Code, webpack) consuming watches simultaneously.

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


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