{"record":{"id":"cd876d8f8a102d6c","repo":"abiosoft/colima","slug":"error-watching-directory-recursively-s-w","errorCode":null,"errorMessage":"error watching directory recursively '%s': %w","messagePattern":"error watching directory recursively '(.+?)': %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"daemon/process/inotify/watch.go","lineNumber":40,"sourceCode":"}\n\ntype defaultWatcher struct {\n\tlog *logrus.Entry\n}\n\n// Watch implements dirWatcher\nfunc (d *defaultWatcher) Watch(ctx context.Context, dirs []string, mod chan<- modEvent) error {\n\tlog := d.log\n\tc := make(chan notify.EventInfo, 1)\n\n\tfor _, dir := range dirs {\n\t\tdir, err := util.CleanPath(dir)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid directory: %w\", err)\n\t\t}\n\t\terr = notify.Watch(dir+\"...\", c, notify.Write)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error watching directory recursively '%s': %w\", dir, err)\n\t\t}\n\t}\n\n\tgo func(ctx context.Context, c chan notify.EventInfo, mod chan<- modEvent) {\n\t\tfor {\n\t\t\tselect {\n\n\t\t\tcase <-ctx.Done():\n\t\t\t\tnotify.Stop(c)\n\t\t\t\tlog.Trace(\"stopping watcher\")\n\t\t\t\tif err := ctx.Err(); err != nil {\n\t\t\t\t\tlog.Trace(fmt.Errorf(\"error found in ctx: %w\", err))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\tcase e := <-c:\n\t\t\t\tpath := e.Path()\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/abiosoft/colima/blob/c3a5f9184d83a197184f897a9f07eb3c01b3bc88/daemon/process/inotify/watch.go#L22-L58","documentation":"Watch registers each cleaned directory with rjeczalik/notify for recursive write events using the 'dir/...' syntax. Failure wraps as \"error watching directory recursively '<dir>'\" with the notify error attached. Typical causes: the directory no longer exists (a container volume deleted after discovery), permission denied for the daemon, or OS-level watch/FSEvents resource errors. Like 114 it returns to the goroutine and is logged, not fatal.","triggerScenarios":"volume directory deleted or renamed between the volume poll and watch registration; permissions blocking the (root) daemon; macOS FSEvents registration failure; watch limit exhaustion on Linux-style inotify backends.","commonSituations":"`docker volume prune` or workload cleanup while the inotify daemon runs; containers with ephemeral mounts; systems with many concurrent watchers.","solutions":["read the wrapped errno: 'no such file or directory' means recreate or let the next refresh drop the dir; 'permission denied' means fix access","restart colima if watchers stop tracking new volume sets","raise watch/file descriptor limits if the cause is resource exhaustion"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"for _, dir := range dirs {\n    if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {\n        continue // pruned/deleted volume: skip rather than fail registration\n    }\n    _ = notify.Watch(dir+\"...\", c, notify.Write)\n}","typeGuard":null,"tryCatchPattern":"if err := notify.Watch(dir+\"...\", c, notify.Write); err != nil {\n    if os.IsNotExist(err) {\n        continue // volume vanished: next 5s refresh drops it\n    }\n    return fmt.Errorf(\"error watching directory recursively '%s': %w\", dir, err)\n}","preventionTips":["stat each directory immediately before registering a watch","expect watch races after `docker volume prune` and let the poll rebuild","track watch/fd limits on hosts with many mounted volumes"],"tags":["inotify","fsevents","watcher","filesystem"],"backgroundTag":null,"analyzedSha":"c3a5f9184d83a197184f897a9f07eb3c01b3bc88","analyzedAt":"2026-08-15T18:58:08.334Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}