thanos-io/thanos · error

unable to create config reloader

Error message

unable to create config reloader

What it means

Raised when the background config-file reloader (extconfig.NewRelacer-style watcher over the endpoint config) cannot be created. The reloader watches the endpoint config file and re-parses/validates it on change; if its construction fails (e.g., no path to watch or watcher setup error), provider creation fails with this wrapper.

Solutions

  1. Check the chained error; ensure the config file path passed to --endpoint-config is absolute and exists so the watcher can attach.
  2. Avoid watching files on NFS/tmpfs; copy the config to a local path or use static --endpoint flags instead.
  3. Verify --endpoint-config-reload-interval (configReloadInterval) is a positive duration.
  4. Test fsnotify on the target filesystem; if unsupported, run Thanos with a local bind-mounted copy of the config.

Example fix

// before
reloader, err := extconfig.NewRelacer(configFile, logger, reg, func(f *file.Content) { ... })
if err != nil { return nil, errors.Wrapf(err, "unable to create config reloader") }
// after: skip watcher when path is not watchable
if _, err := os.Stat(configFile.Path()); err == nil && isLocalFS(configFile.Path()) {
    reloader, err = extconfig.NewRelacer(configFile, logger, reg, onUpdate)
    if err != nil { return nil, errors.Wrapf(err, "unable to create config reloader") }
}
Defensive patterns

Strategy: fallback

Validate before calling

if _, err := os.Stat(configFile.Path()); err != nil { return errors.Wrap(err, "endpoint config must exist to create reloader") }

Type guard

func watchable(p string) bool { return p != "" && isLocalFilesystem(p) }

Try / catch

res, err := newEndpointConfigProvider(...)
if err != nil && strings.Contains(err.Error(), "unable to create config reloader") {
    logger.Warn("falling back to static endpoints without reload")
    res = staticProvider
}

Prevention

When it happens

Trigger: newEndpointConfigProvider calls the reloader constructor with the config file path and update callback; constructor returns error because the file path is empty/invalid for watching or the filesystem watcher (fsnotify) fails to initialize.

Common situations: Passing an endpoint-config flag on a filesystem that doesn't support inotify (some NFS/network mounts); misconfigured reload interval (<=0) accepted by flags but rejected by reloader;Thanos binary built without fsnotify support.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/018034908c89a203. Report an issue: GitHub.

Appendix: source

Thrown at cmd/thanos/endpointset.go:279

	if err := extkingpin.PathContentReloader(context.Background(), configFile, logger, func() {
		res.mu.Lock()
		defer res.mu.Unlock()

		level.Info(logger).Log("msg", "reloading endpoint config")
		cfg, err := res.parse(configFile)
		if err != nil {
			level.Error(logger).Log("msg", "failed to reload endpoint config", "err", err)
			return
		}
		res.addStaticEndpoints(&cfg)
		if err := validateEndpointConfig(&cfg); err != nil {
			level.Error(logger).Log("msg", "failed to validate endpoint config", "err", err)
			return
		}
		res.cfg = cfg
	}, configReloadInterval); err != nil {
		return nil, errors.Wrapf(err, "unable to create config reloader")
	}
	return res, nil
}

func setupEndpointSet(
	g *run.Group,
	comp component.Component,
	reg prometheus.Registerer,
	logger log.Logger,
	configFile fileContent,
	configReloadInterval time.Duration,
	legacyFileSDFiles []string,
	legacyFileSDInterval time.Duration,
	legacyEndpoints []string,
	legacyEndpointGroups []string,
	legacyStrictEndpoints []string,
	legacyStrictEndpointGroups []string,
	dnsSDResolver string,

View on GitHub (pinned to 35b8b99117)