{"record":{"id":"bf746bf1dd0cec2a","repo":"thanos-io/thanos","slug":"add-config-file-s-to-watcher","errorCode":null,"errorMessage":"add config file %s to watcher","messagePattern":"add config file (.+?) to watcher","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/reloader/reloader.go","lineNumber":289,"sourceCode":"// watch interval.\nfunc (r *Reloader) Watch(ctx context.Context) error {\n\tif r.cfgFile == \"\" && len(r.cfgDirs) == 0 && len(r.watchedDirs) == 0 {\n\t\tlevel.Info(r.logger).Log(\"msg\", \"nothing to be watched\")\n\t\t<-ctx.Done()\n\t\treturn nil\n\t}\n\n\tif _, ok := r.tr.(*PIDReloader); ok {\n\t\tlevel.Info(r.logger).Log(\"msg\", \"reloading via process signal\")\n\t} else {\n\t\tlevel.Info(r.logger).Log(\"msg\", \"reloading via HTTP\")\n\t}\n\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.","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/reloader/reloader.go#L271-L307","documentation":"Thanos Reloader's Watch adds the main configuration file to an fsnotify watcher so config changes trigger a reload. This error is returned when watcher.addFile(r.cfgFile) fails — most often because the config file does not exist or is not readable at the given path — and the whole Watch (and the component startup using it) aborts.","triggerScenarios":"Watch (pkg/reloader/reloader.go:289) is called with r.cfgFile set to a path that does not exist, is a directory instead of a file, lacks read permission, or is on an unwatchable filesystem; watcher.addFile returns the fsnotify/OS error, wrapped as 'add config file %s to watcher'.","commonSituations":"Typo in the --rule-dir/--config-file flag path; container image where the config was never mounted; file on a tmpfs/network mount unsupported by inotify; permissions changed after deployment.","solutions":["Verify the file exists and is readable: ls -l <path> (or kubectl exec + ls in the container).","Correct the flag/value pointing at the config file in the component's arguments.","Ensure the config file is actually mounted into the container (ConfigMap/volume) before startup.","Place configs on a local filesystem that supports inotify instead of some network mounts."],"exampleFix":"// before\n--config-file=/etc/thanos/wrong-name.yml\n// after\n--config-file=/etc/thanos/rules.yml","handlingStrategy":"validation","validationCode":"info, err := os.Stat(cfgFile)\nif err != nil || info.IsDir() {\n    return fmt.Errorf(\"config file %s missing or not a file\", cfgFile)\n}","typeGuard":null,"tryCatchPattern":"if err := reloader.Watch(ctx); err != nil {\n    if strings.Contains(err.Error(), \"add config file\") {\n        logger.Error(\"config file path invalid; check mount and flag value\", \"err\", err)\n        os.Exit(1)\n    }\n}","preventionTips":["Validate config paths at container startup with a pre-start check.","Mount configs before the process starts and verify with readiness probes.","Avoid network filesystems lacking inotify for watched configs."],"tags":["config","filesystem","watcher","thanos"],"backgroundTag":"file-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"}