{"record":{"id":"fb6278281282828e","repo":"thanos-io/thanos","slug":"add-directory-s-to-watcher","errorCode":null,"errorMessage":"add directory %s to watcher","messagePattern":"add directory (.+?) to watcher","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/reloader/reloader.go","lineNumber":302,"sourceCode":"\n\tdefer runutil.CloseWithLogOnErr(r.logger, r.watcher, \"config watcher close\")\n\n\tif r.cfgFile != \"\" {\n\t\tif err := r.watcher.addFile(r.cfgFile); err != nil {\n\t\t\treturn errors.Wrapf(err, \"add config file %s to watcher\", r.cfgFile)\n\t\t}\n\t\tinitialSyncCtx, initialSyncCancel := context.WithTimeout(ctx, r.watchInterval)\n\t\terr := r.apply(initialSyncCtx)\n\t\tinitialSyncCancel()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tfor _, cfgDir := range r.cfgDirs {\n\t\tdir := cfgDir.Dir\n\t\tif err := r.watcher.addDirectory(dir); err != nil {\n\t\t\treturn errors.Wrapf(err, \"add directory %s to watcher\", dir)\n\t\t}\n\t}\n\n\tif r.watchInterval == 0 {\n\t\t// Skip watching the file-system.\n\t\treturn nil\n\t}\n\n\tfor _, dir := range r.watchedDirs {\n\t\tif err := r.watcher.addDirectory(dir); err != nil {\n\t\t\treturn errors.Wrapf(err, \"add directory %s to watcher\", dir)\n\t\t}\n\t}\n\n\t// Start watching the file-system.\n\tvar wg sync.WaitGroup\n\twg.Go(func() {\n\t\tr.watcher.run(ctx)","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/reloader/reloader.go#L284-L320","documentation":"Thanos Reloader's Watch also registers each configured directory (r.cfgDirs) with the fsnotify watcher so new/changed files in those directories trigger reloads. This error is returned when watcher.addDirectory(dir) fails — the directory does not exist, is a file, or is not readable/watchable — aborting Watch.","triggerScenarios":"Watch (pkg/reloader/reloader.go:302) iterates r.cfgDirs; for a dir whose path is missing, is not a directory, or cannot be opened for watching, addDirectory returns an error wrapped as 'add directory %s to watcher'.","commonSituations":"--rule-dir pointing to a non-existent path; directory mounted as a file or not yet mounted at container start; permission issues after securityContext changes; network filesystems lacking inotify support.","solutions":["Verify the directory exists and is a directory: ls -ld <dir> inside the container.","Fix the --rule-dir (or equivalent) flag value; pre-create the directory if empty dirs are valid.","Ensure the volume/ConfigMap is mounted before the component starts (init order, subPath mounts).","Check filesystem permissions and use a locally-mounted filesystem that supports inotify."],"exampleFix":"// before: dir never created in the image\n--rule-dir=/etc/thanos/rules/\n// after: create it first\nRUN mkdir -p /etc/thanos/rules && --rule-dir=/etc/thanos/rules/","handlingStrategy":"validation","validationCode":"for _, d := range cfgDirs {\n    info, err := os.Stat(d.Dir)\n    if err != nil || !info.IsDir() {\n        return fmt.Errorf(\"config dir %s missing or not a directory\", d.Dir)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := reloader.Watch(ctx); err != nil {\n    if strings.Contains(err.Error(), \"add directory\") {\n        logger.Error(\"rule directory path invalid; check mount and flag value\", \"err\", err)\n        os.Exit(1)\n    }\n}","preventionTips":["Pre-create rule directories in the container image or via initContainers.","Ensure volumes are mounted before the reloader starts.","Keep watched directories on local, inotify-capable filesystems."],"tags":["config","filesystem","watcher","thanos"],"backgroundTag":"directory-not-found","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}