{"record":{"id":"ec420fa62b0a0b59","repo":"crowdsecurity/crowdsec","slug":"while-reading-s-w","errorCode":null,"errorMessage":"while reading %s: %w","messagePattern":"while reading (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/hubtest/coverage.go","lineNumber":116,"sourceCode":"\n\tfor i, name := range pkeys {\n\t\tcoverage[i] = Coverage{\n\t\t\tName:       name,\n\t\t\tTestsCount: 0,\n\t\t\tPresentIn:  make(map[string]bool),\n\t\t}\n\t}\n\n\t// parser the expressions a-la-oneagain\n\tpasserts, err := filepath.Glob(filepath.Join(hubDir, \".tests\", \"*\", \"parser.assert\"))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"while find parser asserts: %w\", err)\n\t}\n\n\tfor _, assert := range passerts {\n\t\tfile, err := os.Open(assert)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"while reading %s: %w\", assert, err)\n\t\t}\n\n\t\tscanner := bufio.NewScanner(file)\n\t\tfor scanner.Scan() {\n\t\t\tline := scanner.Text()\n\t\t\tlog.Debugf(\"assert line : %s\", line)\n\n\t\t\tmatch := parserResultRE.FindStringSubmatch(line)\n\t\t\tif len(match) == 0 {\n\t\t\t\tlog.Debugf(\"%s doesn't match\", line)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tsidx := parserResultRE.SubexpIndex(\"parser\")\n\t\t\tcapturedParser := match[sidx]\n\n\t\t\tfor idx, pcover := range coverage {\n\t\t\t\tif pcover.Name == capturedParser {","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/hubtest/coverage.go#L98-L134","documentation":"After globbing parser.assert files, GetParsersCoverage opens each one with os.Open. If opening a specific assert file fails, the function stops and returns 'while reading <path>: <err>'. The wrapped os error (e.g. permission denied) identifies the actual cause.","triggerScenarios":"os.Open fails on a parser.assert path: the file was deleted between glob and open, the file is a directory named parser.assert, or the process lacks read permission on it.","commonSituations":"Tests directory mounted read-only or owned by another user (CI running as non-root); a stale glob result after the hub cache was concurrently updated; someone created a directory named parser.assert.","solutions":["Check permissions on the reported parser.assert path (ls -l) and chmod/chown so the running user can read it","Verify the path is a regular file, not a directory; remove/recreate it if wrong","Re-run hub update / re-checkout to replace a truncated or missing assert file","Run hubtest with the same user that owns the hub directory"],"exampleFix":"// before\n-rw------- parser.assert  (owned by root, hubtest runs as ci)\n// after\nchmod 644 parser.assert && chown ci:ci parser.assert","handlingStrategy":"try-catch","validationCode":"info, err := os.Stat(assertPath)\nif err != nil || info.IsDir() { return fmt.Errorf(\"unreadable assert %s\", assertPath) }\nif f, err := os.Open(assertPath); err == nil { f.Close() }","typeGuard":null,"tryCatchPattern":"cov, err := hubtest.GetParsersCoverage(hubDir, ...)\nif err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) { log.Fatalf(\"cannot read %s: %v — check permissions\", pe.Path, pe.Err) }\n}","preventionTips":["Ensure the CI user owns or can read the hub tests directory","Avoid concurrent hub cache updates during coverage runs","Verify assert files are regular files after cloning"],"tags":["filesystem","file-open","permissions","hubtest"],"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-14T00:17:10.932Z"}