crowdsecurity/crowdsec · error

unable to read file %s : %w

Error message

unable to read file %s : %w

What it means

AppsecConfig.LoadByPath reads the appsec config file from disk before parsing it. If os.ReadFile fails (missing file, permission denied, path is a directory), the read error is wrapped with the file path. LoadByPath is the entry point for loading appsec configs both from the hub and from arbitrary local paths, so this fires when the file cannot be opened at all.

Source

Thrown at pkg/appsec/appsec.go:665

}

func (wc *AppsecConfig) SetUpLogger() {
	if wc.LogLevel == nil {
		lvl := wc.Logger.Logger.GetLevel()
		wc.LogLevel = &lvl
	}

	/* wc.Name is actually the datasource name.*/
	wc.Logger = wc.Logger.Dup().WithField("name", wc.Name)
	wc.Logger.Logger.SetLevel(*wc.LogLevel)
}

func (wc *AppsecConfig) LoadByPath(file string) error {
	wc.Logger.Debugf("loading config %s", file)

	yamlFile, err := os.ReadFile(file)
	if err != nil {
		return fmt.Errorf("unable to read file %s : %w", file, err)
	}

	// as  LoadByPath can be called several time, we append rules/hooks, but override other options
	var tmp AppsecConfig

	err = yaml.UnmarshalStrict(yamlFile, &tmp)
	if err != nil {
		return fmt.Errorf("unable to parse yaml file %s : %w", file, err)
	}

	// Normalize phase-scoped sections: merge rules, options, and variables_tracking
	// into flat fields. Hooks stay in the phase sections for Build() to compile separately.
	tmp.normalizePhaseScoped()

	if wc.Name == "" && tmp.Name != "" {
		wc.Name = tmp.Name
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the file exists at the printed path and fix the path (ls the appsec-configs directory)
  2. Fix file permissions/ownership so the crowdsec user can read it
  3. Re-install the hub appsec config (cscli hub update / cscli appsec-configs install) if files were deleted
  4. If mounting configs in a container, verify the volume mount maps the file into the container path

Example fix

// before
/appsec/configs/rules.yaml  # path does not exist
// after
/appsec/configs/crowdsecurity/virtual-patching.yaml  # actual hub-installed path
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Calling LoadByPath(file) where the file does not exist, is unreadable due to permissions, or is a directory; hub Load() passing item.State.LocalPath for an item whose files were deleted or moved after install.

Common situations: Typos in the appsec config path in acquis or config; crowdsec running as a user without read permission on /etc/crowdsec/appsec-configs/*; hub item installed state out of sync with the filesystem (files deleted manually); container image missing the config directory.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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