gastownhall/beads · error
failed to read file: %w
Error message
failed to read file: %w
What it means
readBodyFile wraps io.ReadAll failures with this error: the file (or stdin pipe) was opened successfully but reading its contents failed. This is rarer than open failures and typically indicates I/O problems — a failing disk, a broken pipe on stdin, or reading a special/character device that errors mid-read.
Source
Thrown at cmd/bd/flags.go:206
// If filePath is "-", reads from stdin.
func readBodyFile(filePath string) (string, error) {
var reader io.Reader
if filePath == "-" {
reader = os.Stdin
} else {
// #nosec G304 - filePath comes from user flag, validated by caller
file, err := os.Open(filePath)
if err != nil {
return "", fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
reader = file
}
content, err := io.ReadAll(reader)
if err != nil {
return "", fmt.Errorf("failed to read file: %w", err)
}
return string(content), nil
}
// textSources names the places a command can take body text from: stdin, a
// file path, an explicit text flag, then positional args. A non-nil stdin
// means --stdin was given. flagName names the text flag (e.g. "--response")
// in conflict errors and always accompanies flagText. flagSet marks the text
// flag as explicitly passed (cobra's Changed), so an empty flag value still
// counts as a source — like a blank positional — rather than as absent.
type textSources struct {
stdin io.Reader
filePath string
flagText string
flagName string
flagSet bool
positional []stringView on GitHub (pinned to 71377f2769)
Solutions
- If using '-' with a pipe, check that the upstream command completed successfully (its exit status) and re-run the pipeline
- Retry reading the file with cat <path> to confirm the file itself is readable; check dmesg/disk health if reads fail system-wide
- Copy the file to local disk if it lives on a flaky network mount, then retry the bd command
- Pass the content inline or via an editor instead of a file if the source is unreliable
Example fix
// before: upstream failure silently truncates the pipe ./gen-notes | bd update bd-1 --description-file=- // failed to read file: read ...: broken pipe // after: propagate upstream failure before feeding bd notes=$(./gen-notes) && printf '%s' "$notes" | bd update bd-1 --description-file=-
Defensive patterns
Strategy: try-catch
Validate before calling
path := filePath
if path != "-" {
if _, err := os.ReadFile(path); err != nil {
return fmt.Errorf("body file not readable: %w", err)
}
} Try / catch
content, err := readBodyFile(flagPath)
if err != nil {
var perr *os.PathError
if errors.As(err, &perr) {
return fmt.Errorf("reading body %s: %v", flagPath, perr.Err)
}
return err
} Prevention
- Check the exit status of upstream commands piping into '-' before running bd
- Keep files on reliable local storage; avoid flaky network mounts for flag-file input
- Test with `cat <path> > /dev/null` if reads fail to isolate disk vs. CLI issues
- Prefer inline text or stdin for ephemeral/generated content instead of special files
When it happens
Trigger: Passing a file flag pointing at a special file (e.g. /dev files) that errors on read; disk or network filesystem failure mid-read; stdin ('-') receiving a broken pipe or being closed by the upstream process; permission changes after open on some filesystems.
Common situations: Piping output from a command that died mid-stream (broken pipe into `bd ... --description-file=-`); reading files on a disconnected NFS/network mount; hardware/disk errors on the volume holding the file.
Related errors
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d5a98594a072f3b1.
Report an issue: GitHub.