crowdsecurity/crowdsec · critical

could not create fsnotify watcher: %w

Error message

could not create fsnotify watcher: %w

What it means

Configure creates the fsnotify watcher with fsnotify.NewWatcher(); if the OS refuses (inotify instances/watches exhausted on Linux, or kqueue limitations), it returns "could not create fsnotify watcher: %w". This happens before any directory watch is added, so the whole file datasource fails to start.

Source

Thrown at pkg/acquisition/modules/file/config.go:90

	return nil
}

func (s *Source) Configure(_ context.Context, yamlConfig []byte, logger *log.Entry, metricsLevel metrics.AcquisitionMetricsLevel) error {
	s.logger = logger
	s.metricsLevel = metricsLevel

	err := s.UnmarshalConfig(yamlConfig)
	if err != nil {
		return err
	}

	s.watchedDirectories = make(map[string]bool)
	s.tailMapMutex = &sync.RWMutex{}
	s.tails = make(map[string]bool)

	s.watcher, err = fsnotify.NewWatcher()
	if err != nil {
		return fmt.Errorf("could not create fsnotify watcher: %w", err)
	}

	s.logger.Tracef("Actual FileAcquisition Configuration %+v", s.config)

	for _, pattern := range s.config.Filenames {
		if s.config.ForceInotify {
			directory := filepath.Dir(pattern)
			s.logger.Infof("Force add watch on %s", directory)

			if !s.watchedDirectories[directory] {
				err = s.watcher.Add(directory)
				if err != nil {
					s.logger.Errorf("Could not create watch on directory %s : %s", directory, err)
					continue
				}

				s.watchedDirectories[directory] = true
			}

View on GitHub (pinned to 909b515798)

Solutions

  1. Raise the kernel limit: `sudo sysctl fs.inotify.max_user_instances=1024` (and max_user_watches=1048576) and persist it in /etc/sysctl.conf.
  2. In containers/K8s, raise the host-level sysctl or use a privileged/sysctl-tolerant pod spec.
  3. As a fallback, set poll_without_inotify: true in the file source config to poll instead of using inotify.
  4. Check current usage: `sysctl fs.inotify.max_user_instances` vs. per-user inotify instances (`find /proc/*/fd -lname anon_inode:inotify | wc -l`).

Example fix

// kernel tuning
sudo sysctl -w fs.inotify.max_user_instances=1024
// or config fallback (acquis.yaml)
source: file
poll_without_inotify: true
filenames:
  - /var/log/*.log
Defensive patterns

Strategy: fallback

Validate before calling

// Go: probe inotify availability before configuring the watcher
inst, err := os.ReadFile("/proc/sys/fs/inotify/max_user_instances")
if err == nil {
	if n, _ := strconv.Atoi(strings.TrimSpace(string(inst))); n > 0 && n <= usedInstances() {
		cfg.PollWithoutInotify = boolPtr(true) // fall back to polling
	}
}

Try / catch

if err := src.Configure(ctx, cfgYAML, logger, metricsLevel); err != nil {
	if strings.Contains(err.Error(), "could not create fsnotify watcher") {
		// raise fs.inotify.max_user_instances or switch to poll_without_inotify: true
	}
}

Prevention

When it happens

Trigger: fsnotify.NewWatcher() returning an OS error: Linux inotify instances exhausted (fs.inotify.max_user_instances reached by this process/container), or running in a container/namespace where inotify is unavailable.

Common situations: Containers with low inotify limits (common in Kubernetes pods); many concurrent watchers on one host (IDEs, other agents) draining max_user_instances; LXC/WSL1 environments lacking inotify support.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/0759274fd7fd741c. Report an issue: GitHub.