{"record":{"id":"d02c5eed8d00d175","repo":"crowdsecurity/crowdsec","slug":"failed-to-stat-s-v","errorCode":null,"errorMessage":"failed to stat %s : %v","messagePattern":"failed to stat (.+?) : (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/parser/stage.go","lineNumber":77,"sourceCode":"\t}\n\n\tsort.Strings(pctx.Stages)\n\tlog.Infof(\"Loaded %d nodes from %d stages\", len(allNodes), len(pctx.Stages))\n\n\treturn allNodes, nil\n}\n\nfunc processStageFile(stageFile Stagefile, pctx *UnixParserCtx, ectx EnricherCtx) ([]Node, error) {\n\tif !strings.HasSuffix(stageFile.Filename, \".yaml\") && !strings.HasSuffix(stageFile.Filename, \".yml\") {\n\t\tlog.Warningf(\"skip non yaml : %s\", stageFile.Filename)\n\t\treturn nil, nil\n\t}\n\n\tlog.Debugf(\"loading parser file '%s'\", stageFile)\n\n\tst, err := os.Stat(stageFile.Filename)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to stat %s : %v\", stageFile, err)\n\t}\n\n\tif st.IsDir() {\n\t\treturn nil, nil\n\t}\n\n\tyamlFile, err := os.Open(stageFile.Filename)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"can't access parsing configuration file %s : %s\", stageFile.Filename, err)\n\t}\n\tdefer yamlFile.Close()\n\t// process the yaml\n\tdec := yaml.NewDecoder(yamlFile)\n\tdec.SetStrict(true)\n\n\tvar nodes []Node\n\n\tnodesCount := 0","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/parser/stage.go#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nls -la /etc/crowdsec/parsers/s01-parse/ Broken -> missing_target.yaml\n# after (reinstall the broken parser or remove dangling symlink)\ncscli parsers remove crowdsecurity/broken-parser\ncscli parsers install crowdsecurity/broken-parser","handlingStrategy":"validation","validationCode":"info, err := os.Stat(path)\nif err != nil || info.IsDir() { return fmt.Errorf(\"parser file %s unreadable: %w\", path, err) }","typeGuard":"func fileExists(p string) bool { _, err := os.Stat(p); return !os.IsNotExist(err) }","tryCatchPattern":"nodes, err := processStageFile(stageFile, pctx, ectx)\nif err != nil {\n    log.Warnf(\"skipping stage file: %v\", err)\n    return nil, err\n}","preventionTips":["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"],"tags":["filesystem","config","parser","stat"],"backgroundTag":"file-not-found","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}