getzola/zola · error

Can't watch `{entry}`: OS file watch limit reached. Check ho

Error message

Can't watch `{entry}`: OS file watch limit reached. Check how to raise it for your OS.

What it means

The serve command registers filesystem watchers via the notify debouncer; when the OS reports ErrorKind::MaxFilesWatch, it is converted into this error explaining that the OS inotify/watch limit is exhausted. This is deliberate so users get an actionable message instead of a generic watch failure.

Source

Thrown at src/cmd/serve.rs:613

    //   - the path is mandatory but does not exist (eg. config.toml)
    //   - the path exists but has incorrect permissions
    // watchers will contain the paths we're actually watching
    let mut watchers = Vec::new();
    for (entry, watch_mode, recursive_mode) in watch_this {
        let watch_path = root_dir.join(entry);
        let should_watch = match watch_mode {
            WatchMode::Required => true,
            WatchMode::Optional => watch_path.exists(),
            WatchMode::Condition(b) => b && watch_path.exists(),
        };
        if should_watch {
            debouncer
                .watch(root_dir.join(entry), recursive_mode)
                .map_err(|e| {
                    match e.kind {
                        ErrorKind::MaxFilesWatch => {
                            // https://github.com/getzola/zola/issues/1803
                            anyhow!("Can't watch `{entry}`: OS file watch limit reached. Check how to raise it for your OS.")
                        }
                        _ => anyhow!("Can't watch `{entry}` for changes in folder `{}`. Does it exist, and do you have correct permissions?", root_dir.display())
                    }
                })?;
            watchers.push(entry.to_string());
        }
    }

    let output_path = site.output_path.clone();
    create_directory(&output_path)?;

    // static_root needs to be canonicalized because we do the same for the http server.
    let static_root = std::fs::canonicalize(&output_path).unwrap();

    // Create broadcast channel for WebSocket live reload
    let (reload_tx, _) = broadcast::channel::<String>(100);
    let broadcaster = reload_tx.clone();

View on GitHub (pinned to 61d3082821)

Solutions

  1. Raise the Linux inotify limit: sudo sysctl fs.inotify.max_user_watches=524288 and persist it in /etc/sysctl.conf
  2. Reduce the watched surface: ignore or exclude large generated directories (node_modules, public/) from the project
  3. Close other applications consuming inotify watches (editors, other dev servers)
  4. On containers/WSL, increase inotify limits for the VM or use a native filesystem rather than a bind mount

Example fix

// before
$ zola serve
// Can't watch `...`: OS file watch limit reached.
// after
$ sudo sysctl fs.inotify.max_user_watches=524288
$ zola serve
Defensive patterns

Strategy: validation

Validate before calling

// Check current inotify watch quota on Linux before serving:
// cat /proc/sys/fs/inotify/max_user_watches
// count usage: find ~/project -type d | wc -l

Try / catch

// shell
zola serve || {
  case "$?" in
    1) sudo sysctl fs.inotify.max_user_watches=524288 && zola serve ;;
  esac
}

Prevention

When it happens

Trigger: zola serve on a large project (or when many other apps consume watches) where the number of files/directories to watch exceeds the OS limit — inotify max_user_watches on Linux is the typical case.

Common situations: Linux kernel default fs.inotify.max_user_watches=8192 with a big site or node_modules in the watched tree; running many watchers concurrently (editors, other dev servers) exhausting the user quota; containers with tight inotify limits.

Related errors


AI-assisted analysis of getzola/zola@61d3082821 (2026-09-03). Data as JSON: /api/errors/0d0da406c3bad2a2. Report an issue: GitHub.