crowdsecurity/crowdsec · error
failed to stat %s : %v
Error message
failed to stat %s : %v
What it means
Wraps an os.Stat failure when loading a parser stage file during LoadStages → processStageFile. The %s is the stageFile descriptor and %v the OS error (typically 'no such file or directory' or a permission error). CrowdSec cannot even inspect the parser config file, so stage loading aborts for that path.
Source
Thrown at pkg/parser/stage.go:77
}
sort.Strings(pctx.Stages)
log.Infof("Loaded %d nodes from %d stages", len(allNodes), len(pctx.Stages))
return allNodes, nil
}
func processStageFile(stageFile Stagefile, pctx *UnixParserCtx, ectx EnricherCtx) ([]Node, error) {
if !strings.HasSuffix(stageFile.Filename, ".yaml") && !strings.HasSuffix(stageFile.Filename, ".yml") {
log.Warningf("skip non yaml : %s", stageFile.Filename)
return nil, nil
}
log.Debugf("loading parser file '%s'", stageFile)
st, err := os.Stat(stageFile.Filename)
if err != nil {
return nil, fmt.Errorf("failed to stat %s : %v", stageFile, err)
}
if st.IsDir() {
return nil, nil
}
yamlFile, err := os.Open(stageFile.Filename)
if err != nil {
return nil, fmt.Errorf("can't access parsing configuration file %s : %s", stageFile.Filename, err)
}
defer yamlFile.Close()
// process the yaml
dec := yaml.NewDecoder(yamlFile)
dec.SetStrict(true)
var nodes []Node
nodesCount := 0View on GitHub (pinned to 909b515798)
Solutions
- Check the printed path: does the file exist and is the symlink target intact?
- Reinstall/refresh the hub: `cscli hub update && cscli hub upgrade`
- Fix permissions on the parsers directory (readable by the crowdsec user)
- Correct the config path (config_dir/parsers dir) in crowdsec.yaml
Example fix
# before ls -la /etc/crowdsec/parsers/s01-parse/ Broken -> missing_target.yaml # after (reinstall the broken parser or remove dangling symlink) cscli parsers remove crowdsecurity/broken-parser cscli parsers install crowdsecurity/broken-parser
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(path)
if err != nil || info.IsDir() { return fmt.Errorf("parser file %s unreadable: %w", path, err) } Type guard
func fileExists(p string) bool { _, err := os.Stat(p); return !os.IsNotExist(err) } Try / catch
nodes, err := processStageFile(stageFile, pctx, ectx)
if err != nil {
log.Warnf("skipping stage file: %v", err)
return nil, err
} Prevention
- After hub operations, verify no dangling symlinks under parsers/
- Run crowdsec as a user with read access to /etc/crowdsec
- Mount config volumes read-only but present in containers
When it happens
Trigger: Calling processStageFile (via LoadStages) when stageFile.Filename does not exist, was removed/symlinked away, or the path is inaccessible due to permissions or a broken symlink.
Common situations: Hub partially updated leaving dangling symlinks in /etc/crowdsec/parsers/, wrong config_dir in acquis/crowdsec.yaml, running crowdsec in a container without the parsers dir mounted, permission changes on the config tree.
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
- can't access parsing configuration file %s : %s
- could not access CRL file: %w
- failed to get absolute path of %q: %w
- while opening %s: %w
- failed to open feature flags file: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/d02c5eed8d00d175.
Report an issue: GitHub.