{"record":{"id":"99051bdbf8ac3929","repo":"crowdsecurity/crowdsec","slug":"can-t-access-parsing-configuration-file-s-s","errorCode":null,"errorMessage":"can't access parsing configuration file %s : %s","messagePattern":"can't access parsing configuration file (.+?) : (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/parser/stage.go","lineNumber":86,"sourceCode":"\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\n\n\tfor {\n\t\tnode := Node{}\n\t\tnode.OnSuccess = \"continue\" // default behavior is to continue\n\n\t\tif err = dec.Decode(&node); err != nil {\n\t\t\tif errors.Is(err, io.EOF) {\n\t\t\t\tlog.Tracef(\"End of yaml file\")\n\t\t\t\tbreak","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/parser/stage.go#L68-L104","documentation":"Wraps an os.Open failure when reading a parser stage YAML file in processStageFile. Unlike 1215, the file stat'ed OK but opening it failed — typically a permission problem (or a race where the file vanished between stat and open). CrowdSec aborts loading that stage file because the YAML cannot be read.","triggerScenarios":"Calling processStageFile (via LoadStages) when os.Open(stageFile.Filename) returns an error: file not readable by the crowdsec user, SELinux/AppArmor denial, or file removed between Stat and Open.","commonSituations":"Config files owned by root with 0600 while crowdsec runs as the crowdsec user, hardened SELinux contexts after manual copy of parser files, read-only or FUSE mounts denying open.","solutions":["Check file ownership/permissions: `ls -l <file>` and ensure the crowdsec user can read it","Restore proper SELinux context (`restorecon -Rv /etc/crowdsec`) if SELinux denied the open","Re-copy the parser file with correct ownership from the hub","Reinstall the parser via cscli to replace a corrupted local file"],"exampleFix":"// before\n-rw------- root root /etc/crowdsec/parsers/s01-parse/custom.yaml\n// after\nchown crowdsec:crowdsec /etc/crowdsec/parsers/s01-parse/custom.yaml\nchmod 640 /etc/crowdsec/parsers/s01-parse/custom.yaml","handlingStrategy":"validation","validationCode":"f, err := os.Open(path)\nif err != nil { return fmt.Errorf(\"cannot read parser file %s: %w\", path, err) }\nf.Close()","typeGuard":"func readableBy(path string, uid uint32) bool { info, err := os.Stat(path); return err == nil && info.Mode().Perm()&0400 != 0 }","tryCatchPattern":"if _, err := processStageFile(sf, pctx, ectx); err != nil {\n    log.Errorf(\"stage load failed: %v\", err) // check perms/SELinux\n}","preventionTips":["Deploy parser files with 0644 and proper ownership","Check audit logs for SELinux/AppArmor denials on config paths","Avoid manual root-owned copies into the config tree"],"tags":["filesystem","permissions","config","parser"],"backgroundTag":"file-open-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}