{"record":{"id":"99232becee4102b3","repo":"docker/compose","slug":"hit-os-limits-creating-a-watcher-run-sysctl-fs-i","errorCode":null,"errorMessage":"hit OS limits creating a watcher.\nRun 'sysctl fs.inotify.max_user_instances' to check your inotify limits.\nTo raise them, run 'sudo sysctl fs.inotify.max_user_instances=1024'","messagePattern":"hit OS limits creating a watcher\\.\nRun 'sysctl fs\\.inotify\\.max_user_instances' to check your inotify limits\\.\nTo raise them, run 'sudo sysctl fs\\.inotify\\.max_user_instances=1024'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/watch/watcher_naive.go","lineNumber":304,"sourceCode":"\t}\n\treturn true\n}\n\nfunc (d *naiveNotify) add(path string) error {\n\terr := d.watcher.Add(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\td.numWatches++\n\tnumberOfWatches.Add(1)\n\treturn nil\n}\n\nfunc newWatcher(paths []string) (Notify, error) {\n\tfsw, err := fsnotify.NewWatcher()\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), \"too many open files\") && runtime.GOOS == \"linux\" {\n\t\t\treturn nil, fmt.Errorf(\"hit OS limits creating a watcher.\\n\" +\n\t\t\t\t\"Run 'sysctl fs.inotify.max_user_instances' to check your inotify limits.\\n\" +\n\t\t\t\t\"To raise them, run 'sudo sysctl fs.inotify.max_user_instances=1024'\")\n\t\t}\n\t\treturn nil, fmt.Errorf(\"creating file watcher: %w\", err)\n\t}\n\tMaybeIncreaseBufferSize(fsw)\n\n\terr = fsw.SetRecursive()\n\tisWatcherRecursive := err == nil\n\n\twrappedEvents := make(chan FileEvent)\n\tnotifyList := make(map[string]bool, len(paths))\n\tif isWatcherRecursive {\n\t\tpaths = pathutil.EncompassingPaths(paths)\n\t}\n\tfor _, path := range paths {\n\t\tpath, err := filepath.Abs(path)\n\t\tif err != nil {","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/watch/watcher_naive.go#L286-L322","documentation":"This is the very first operation of newWatcher on the naive path: creating the fsnotify watcher itself allocates a new inotify instance on Linux. When the kernel refuses with 'too many open files' (EMFILE — max_user_instances reached), the code detects the string and returns a actionable remediation message instead of a cryptic error. It includes the exact sysctl commands to inspect and raise the limit.","triggerScenarios":"fsnotify.NewWatcher() failing with EMFILE on Linux: each NewWatcher consumes one inotify instance, and the default max_user_instances (often 128) is exhausted by other watchers (editors, dev servers, sync clients, other compose sessions) before compose starts.","commonSituations":"Long-running developer workstations with many file-watching apps (VS Code, Dropbox, JetBrains IDEs); CI runners or containers with low instance caps; Docker Desktop's Linux VM hitting its limit; reopening many compose watch projects in parallel.","solutions":["Follow the message: run `sudo sysctl fs.inotify.max_user_instances=1024` (inspect first with `sysctl fs.inotify.max_user_instances`).","Persist across reboots: `echo fs.inotify.max_user_instances=1024 | sudo tee /etc/sysctl.d/90-inotify.conf && sudo sysctl --system`.","Reduce competing watchers: close unused editor windows/sync clients or stop other compose watch sessions to free instances.","For Docker Desktop, raise the limit inside the VM's settings or increase allocated resources."],"exampleFix":"# before: default\nsysctl fs.inotify.max_user_instances   # 128 -> watchers fail\n# after\nsudo sysctl fs.inotify.max_user_instances=1024","handlingStrategy":"validation","validationCode":"// Linux: fail fast if inotify instances are already exhausted\nfunc inotifyHeadroom() error {\n    max, _ := strconv.Atoi(strings.TrimSpace(mustRead(\"/proc/sys/fs/inotify/max_user_instances\")))\n    open := countOpenInotifyFds() // scan /proc/self/fd for 'inotify' links\n    if open >= max { return fmt.Errorf(\"inotify instances exhausted; raise fs.inotify.max_user_instances\") }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"hit OS limits creating a watcher\") {\n        // terminal config error: print sysctl remediation, do not retry programmatically\n    }\n    return err\n}","preventionTips":["Persist fs.inotify.max_user_instances=1024 via /etc/sysctl.d/90-inotify.conf on Linux dev hosts.","Limit concurrent watch sessions (editors, sync clients, compose watch) per user.","For Docker Desktop, raise limits inside the VM when running many watchers."],"tags":["go","docker-compose","watch","inotify","linux","resource-limits","os-limits"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}