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
- Check the file exists at the printed path and fix the path (ls the appsec-configs directory)
- Fix file permissions/ownership so the crowdsec user can read it
- Re-install the hub appsec config (cscli hub update / cscli appsec-configs install) if files were deleted
- 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
- Check paths and permissions after packaging
- Reinstall hub items rather than moving files
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
- could not read CRL file: %w
- while creating temp file: %w
- unable to read body: %w
- appsec datasource requires a hub. this is a bug, please repo
- appsec datasource requires a lapi client configuration. this
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/8c36d4ee483a8622.
Report an issue: GitHub.