crowdsecurity/crowdsec · error

failed to stat %s: %w

Error message

failed to stat %s: %w

What it means

Before symlinking, CreateInstallLink runs os.Lstat(dest); if Lstat fails with an error other than NotExist (which is the normal "link missing" case), the operation aborts with this error. It guards against unexpected filesystem states at the destination of the install link.

Source

Thrown at pkg/hubops/enable.go:66

}

// CreateInstallLink creates a symlink between the actual config file at hub.HubDir and hub.ConfigDir.
func CreateInstallLink(i *cwhub.Item) error {
	dest, err := i.PathForInstall()
	if err != nil {
		return err
	}

	destDir := filepath.Dir(dest)
	if err = os.MkdirAll(destDir, os.ModePerm); err != nil {
		return fmt.Errorf("while creating %s: %w", destDir, err)
	}

	if _, err = os.Lstat(dest); err == nil {
		// already exists
		return nil
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("failed to stat %s: %w", dest, err)
	}

	src := i.State.DownloadPath

	if err = os.Symlink(src, dest); err != nil {
		return fmt.Errorf("while creating symlink from %s to %s: %w", src, dest, err)
	}

	i.State.LocalPath = dest

	return nil
}

func (c *EnableCommand) Run(_ context.Context, plan *ActionPlan) error {
	i := c.Item

	fmt.Fprintln(os.Stdout, "enabling " + colorizeItemName(i.FQName()))

View on GitHub (pinned to 909b515798)

Solutions

  1. Check permissions on the destination's parent directory: `ls -ld <destDir>` and fix with chown/chmod.
  2. Inspect the dest path for a broken symlink loop (`ls -l <dest>`, `readlink -f <dest>`).
  3. Remove the problematic leftover entry and re-run the enable command.
  4. Run the command as root if the install directory is root-owned.

Example fix

// inspect and clear a bad destination
ls -ld /etc/crowdsec/parsers/sudo/
sudo rm -rf /etc/crowdsec/parsers/sudo
sudo cscli parsers enable sudo
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Lstat(dest); err != nil && !os.IsNotExist(err) {
    return fmt.Errorf("destination %s in bad state: %w", dest, err)
}

Try / catch

_, err := os.Lstat(dest)
if err != nil && !errors.Is(err, fs.ErrNotExist) {
    // resolve permissions or symlink loop before retrying enable
}

Prevention

When it happens

Trigger: During enable/install when Lstat on the destination path fails due to permission denied on the parent directory, a symlink loop (ELOOP), or I/O error — anything except "file does not exist".

Common situations: Parent install directory not writable/searchable by the running user; corrupt dangling symlink chains left by manual cleanup; filesystem errors on degraded storage.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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