docker/compose · error
creating file watcher: %w
Error message
creating file watcher: %w
What it means
The generic counterpart to the inotify-limit case: fsnotify.NewWatcher() failed for any reason other than the detected 'too many open files' pattern, or the platform is not Linux. The underlying error is wrapped with creating file watcher so the cause survives. Typical causes are fd exhaustion (ulimit -n), EMFILE variants with different wording, or unsupported platforms for the backend.
Source
Thrown at pkg/watch/watcher_naive.go:308
func (d *naiveNotify) add(path string) error {
err := d.watcher.Add(path)
if err != nil {
return err
}
d.numWatches++
numberOfWatches.Add(1)
return nil
}
func newWatcher(paths []string) (Notify, error) {
fsw, err := fsnotify.NewWatcher()
if err != nil {
if strings.Contains(err.Error(), "too many open files") && runtime.GOOS == "linux" {
return nil, fmt.Errorf("hit OS limits creating a watcher.\n" +
"Run 'sysctl fs.inotify.max_user_instances' to check your inotify limits.\n" +
"To raise them, run 'sudo sysctl fs.inotify.max_user_instances=1024'")
}
return nil, fmt.Errorf("creating file watcher: %w", err)
}
MaybeIncreaseBufferSize(fsw)
err = fsw.SetRecursive()
isWatcherRecursive := err == nil
wrappedEvents := make(chan FileEvent)
notifyList := make(map[string]bool, len(paths))
if isWatcherRecursive {
paths = pathutil.EncompassingPaths(paths)
}
for _, path := range paths {
path, err := filepath.Abs(path)
if err != nil {
return nil, fmt.Errorf("newWatcher: %w", err)
}
notifyList[path] = true
}View on GitHub (pinned to ddc4b044b6)
Solutions
- Check the wrapped cause: EMFILE means raise the process fd limit (`ulimit -n 4096` or LimitNOFILE in systemd); ENFILE means the whole system is out of fds — find the fd hog with `lsof | awk '{print $1}' | sort | uniq -c | sort -rn`.
- Verify inotify is permitted: seccomp/cap policies in containers must allow inotify_init1 (try unconfined or adjust the profile).
- Reduce concurrent watchers or restart leaking processes to free descriptors.
Example fix
# before: default soft limit causes EMFILE ulimit -n # 1024 # after ulimit -n 4096 docker compose watch
Defensive patterns
Strategy: try-catch
Validate before calling
// check fd headroom before creating watchers
var rlim syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err == nil {
if countOpenFds() > int(rlim.Cur)-64 {
return fmt.Errorf("raise ulimit -n before starting file watchers")
}
} Try / catch
if err != nil {
var errno syscall.Errno
if errors.As(err, &errno) && (errno == syscall.EMFILE || errno == syscall.ENFILE) {
// EMFILE: raise process fd limit (ulimit -n / LimitNOFILE)
// ENFILE: system-wide exhaustion — identify fd hogs with lsof, no local retry helps
}
return err
} Prevention
- Set LimitNOFILE/ulimit -n adequately for long-running dev tooling.
- Fix fd leaks in plugins and sidecar processes; monitor /proc/<pid>/fd counts.
- In containers, allow inotify syscalls in the seccomp profile.
When it happens
Trigger: fsnotify.NewWatcher() returning an error on a non-Linux OS, or a Linux error string not matching 'too many open files' (e.g. localized messages or 'too many open files in system' variants hitting ENFILE — a system-wide fd limit).
Common situations: Process fd limit (ulimit -n) exhausted by leaked file descriptors in the app or plugins; ENFILE system-wide fd exhaustion on busy hosts; running on an OS where inotify is unavailable (some minimal containers/seccomp profiles block inotify_init).
Related errors
- hit OS limits creating a watcher. Run 'sysctl fs.inotify.max
- error reading .dockerignore: %w
- cannot watch root directory
- os.Stat(%q): %w
- newWatcher: %w
AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15).
Data as JSON: /api/errors/2bd29060d8445318.
Report an issue: GitHub.