crowdsecurity/crowdsec · error

could not lstat() file

Error message

could not lstat() file %s: %w

What it means

setupTailForFile calls os.Lstat to check whether the path is a symlink and warn about rotation-detection limitations. If Lstat fails it returns "could not lstat() file %s: %w". Like the Stat error, this means the path became inaccessible (or was always inaccessible to stat) between the earlier open and this check.

Solutions

  1. Check whether the path (or symlink) still exists: ls -la the path.
  2. If it's a dangling symlink, fix or remove it from the acquisition patterns.
  3. Verify parent directory execute permissions for the crowdsec user.
  4. If the file races constantly with rotation, set poll_without_inotify: true in the acquisition config.
Defensive patterns

Strategy: validation

Validate before calling

// verify path is a resolvable, existing entry
ls -la /var/log/myapp.log
readlink -f /var/log/myapp.log || echo 'dangling symlink'

Prevention

When it happens

Trigger: os.Lstat(file) errors in setupTailForFile during symlink status check, from StreamingAcquisition or checkAndTailFile.

Common situations: Symlink target replaced/removed mid-scan; dangling symlink where the target vanished; permission on symlink resolution; NFS staleness.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at pkg/acquisition/modules/file/run.go:252

	} else {
		networkFS, fsType, err := fsutil.IsNetworkFS(file)
		if err != nil {
			logger.Warningf("Could not get fs type for %s : %s", file, err)
		}

		logger.Debugf("fs for %s is network: %t (%s)", file, networkFS, fsType)

		if networkFS {
			logger.Warnf("Disabling inotify polling on %s as it is on a network share. You can manually set poll_without_inotify to true to make this message disappear, or to false to enforce inotify poll", file)

			pollFile = true
		}
	}

	// Check symlink status
	filink, err := os.Lstat(file)
	if err != nil {
		return fmt.Errorf("could not lstat() file %s: %w", file, err)
	}

	if filink.Mode()&os.ModeSymlink == os.ModeSymlink && !pollFile {
		logger.Warnf("File %s is a symlink, but inotify polling is enabled. Crowdsec will not be able to detect rotation. Consider setting poll_without_inotify to true in your configuration", file)
	}

	// Create the tailer with appropriate configuration
	seekInfo := &tail.SeekInfo{Offset: 0, Whence: io.SeekEnd}
	if s.config.Mode == configuration.CAT_MODE {
		seekInfo.Whence = io.SeekStart
	}

	if seekEnd {
		seekInfo.Whence = io.SeekEnd
	}

	logger.Infof("Starting tail (offset: %d, whence: %d)", seekInfo.Offset, seekInfo.Whence)

View on GitHub (pinned to 909b515798)