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
- Raise the kernel limit: `sudo sysctl fs.inotify.max_user_instances=1024` (and max_user_watches=1048576) and persist it in /etc/sysctl.conf.
- In containers/K8s, raise the host-level sysctl or use a privileged/sysctl-tolerant pod spec.
- As a fallback, set poll_without_inotify: true in the file source config to poll instead of using inotify.
- 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
- Set generous fs.inotify.max_user_instances/max_user_watches on hosts running many watchers.
- Set poll_without_inotify: true in containers known to have tight inotify limits.
- Monitor inotify usage (`find /proc/*/fd -lname anon_inode:inotify | wc -l`) in capacity checks.
- Verify inotify works at container startup with a smoke test before going live.
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
- cannot parse FileAcquisition configuration: %s
- unsupported mode %s for file source
- could not compile regexp %s: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/0759274fd7fd741c.
Report an issue: GitHub.