{"record":{"id":"7c7ac4378fd643e0","repo":"GoogleContainerTools/skaffold","slug":"failed-to-monitor-files-w","errorCode":null,"errorMessage":"failed to monitor files: %w","messagePattern":"failed to monitor files: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/runner/listen.go","lineNumber":69,"sourceCode":"}\n\nfunc (l *SkaffoldListener) LogWatchToUser(out io.Writer) {\n\tl.Trigger.LogWatchToUser(out)\n}\n\n// WatchForChanges listens to a trigger, and when one is received, computes file changes and\n// conditionally runs the dev loop.\nfunc (l *SkaffoldListener) WatchForChanges(ctx context.Context, out io.Writer, devLoop func() error) error {\n\tctxTrigger, cancelTrigger := context.WithCancel(ctx)\n\tdefer cancelTrigger()\n\ttrigger, err := trigger.StartTrigger(ctxTrigger, l.Trigger)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to start trigger: %w\", err)\n\t}\n\n\t// exit if file monitor fails the first time\n\tif err := l.Monitor.Run(l.Trigger.Debounce()); err != nil {\n\t\treturn fmt.Errorf(\"failed to monitor files: %w\", err)\n\t}\n\n\tl.LogWatchToUser(out)\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\tcase <-l.intentChan:\n\t\t\tif err := l.do(devLoop); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase <-trigger:\n\t\t\tif err := l.do(devLoop); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/runner/listen.go#L51-L87","documentation":"skaffold's dev loop (`WatchForChanges`) starts a file monitor (`l.Monitor.Run`) that watches the workspace for file changes and feeds them into a debounced trigger. If the monitor fails on its very first run, the watch loop is aborted immediately with this wrapped error. It means skaffold could not establish the filesystem watcher, so change detection is impossible.","triggerScenarios":"Running `skaffold dev` where `l.Monitor.Run(l.Trigger.Debounce())` returns an error on startup: the underlying watcher (fsnotify) fails to add watch descriptors, e.g. too many open files, watching a directory that was deleted, or watching a path the user cannot read.","commonSituations":"Dev loop over huge directory trees exhausting inotify watches (ulimit), watching a deleted/renamed working directory, permission-restricted folders, or network filesystems (NFS/SMB) that don't support inotify.","solutions":["Raise the inotify watch limit: `sudo sysctl fs.inotify.max_user_watches=524288` (and `fs.inotify.max_user_instances`).","Verify the working directory exists and is readable; re-run skaffold from a valid checkout.","Narrow the watched paths via `watch` config (`ignore`/`includes`) in skaffold.yaml to reduce descriptor usage.","On network filesystems, run the source locally or use `--trigger=manual`/`polling` instead of the default watcher.","Check `ulimit -n` (open file limit) and increase it if very low."],"exampleFix":"// before\nskaffold dev --watch-poll-interval=0  # watching entire $HOME, exhausting inotify\n// after\n# skaffold.yaml\nwatch:\n  ignore:\n    - \"**/node_modules/**\"\n    - \"**/.git/**\"","handlingStrategy":"try-catch","validationCode":"func canWatch(paths ...string) error {\n  for _, p := range paths {\n    if _, err := os.Stat(p); err != nil { return fmt.Errorf(\"watch path %q: %w\", p, err) }\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":"if err := runner.WatchForChanges(ctx, out); err != nil {\n  if strings.Contains(err.Error(), \"failed to monitor files\") {\n    log.Warn(\"file watcher unavailable (check inotify limits); falling back to polling\")\n    // retry with --trigger=polling or manual trigger\n  }\n  return err\n}","preventionTips":["Raise fs.inotify.max_user_watches/max_user_instances on dev machines and CI images.","Configure `watch.ignore` for node_modules, .git, and vendor trees.","Avoid watching network mounts; keep source on a local filesystem.","Check working directory validity before starting dev loops in scripts."],"tags":["filesystem","watcher","dev-loop","inotify"],"backgroundTag":"inotify-watch-limit-exhausted","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}