{"record":{"id":"c8ffbaf05e56563b","repo":"gastownhall/beads","slug":"failed-to-open-file-w-c8ffba","errorCode":null,"errorMessage":"failed to open file: %w","messagePattern":"failed to open file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/markdown.go","lineNumber":271,"sourceCode":"\tscanner := bufio.NewScanner(file)\n\t// Increase buffer size for large markdown files\n\tconst maxScannerBuffer = 1024 * 1024 // 1MB\n\tbuf := make([]byte, maxScannerBuffer)\n\tscanner.Buffer(buf, maxScannerBuffer)\n\treturn scanner\n}\n\nfunc parseMarkdownFile(path string) ([]*IssueTemplate, error) {\n\t// Validate and clean the file path\n\tcleanPath, err := validateMarkdownPath(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// #nosec G304 -- Path is validated by validateMarkdownPath which prevents traversal\n\tfile, err := os.Open(cleanPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to open file: %w\", err)\n\t}\n\tdefer func() {\n\t\t_ = file.Close() // Close errors on read-only operations are not actionable\n\t}()\n\n\tstate := &markdownParseState{}\n\tscanner := createMarkdownScanner(file)\n\n\tfor scanner.Scan() {\n\t\tline := scanner.Text()\n\n\t\t// Check for H2 (new issue)\n\t\tif matches := h2Regex.FindStringSubmatch(line); matches != nil {\n\t\t\tstate.handleH2Header(matches)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check for H3 (section within issue)","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/markdown.go#L253-L289","documentation":"parseMarkdownFile opens the validated path with os.Open; any open failure (permission denied, file vanished between validation and open, I/O error) is wrapped as \"failed to open file: <os error>\". This happens after path validation succeeded, so it usually reflects transient or permission issues rather than a missing file.","triggerScenarios":"os.Open fails on an already-validated .md path: file deleted in a race between Stat and Open, read permission denied, or underlying device/I/O error (e.g. broken symlink surviving Stat, NFS stale handle).","commonSituations":"Files on network mounts going stale; another process deleting the temp file mid-run; restrictive umask/ownership after generation; container user lacking read access to mounted volume.","solutions":["Check file readability: `ls -l <file>` and `test -r <file>`; fix with chmod/chown or run as a user with access","Re-run the command — the file may have been deleted mid-run by a prior step","Verify the file is a regular readable file (not a broken symlink): `readlink -f <file>`","Check mount health if the file is on NFS/network storage"],"exampleFix":"# before (unreadable file)\n-rw------- issues.md  owned by root, bd runs as app user\n# after\nchmod 644 issues.md  # or chown app:app issues.md","handlingStrategy":"try-catch","validationCode":"f, err := os.Open(path)\nif err != nil {\n\treturn fmt.Errorf(\"pre-flight open failed: %w\", err)\n}\nf.Close()","typeGuard":null,"tryCatchPattern":"if err := runImport(path); err != nil {\n\tvar pe *fs.PathError\n\tif errors.As(err, &pe) && errors.Is(pe.Err, os.ErrPermission) {\n\t\t// fix permissions or run as another user, then retry once\n\t} else {\n\t\treturn err\n\t}\n}","preventionTips":["Ensure read permissions for the bd process user","Avoid deleting/regenerating the file while import runs","Keep files on local stable storage when possible"],"tags":["filesystem","io","permissions"],"backgroundTag":"failed-to-open-file","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}