gastownhall/beads · error

reading from stdin: %w

Error message

reading from stdin: %w

What it means

This error wraps a failure that occurred while reading all bytes from the process's stdin stream when a command was invoked with the --stdin flag. It is produced by textFromSources in cmd/bd/flags.go, which collects text from registered sources (--stdin, --file, positional args). The underlying read error (wrapped with %w) usually indicates the stdin stream itself failed (I/O error, closed/broken pipe, or a non-readable stdin), not that the content was invalid.

Source

Thrown at cmd/bd/flags.go:255

// one (echo, heredocs) — while file content is passed through verbatim like
// every other file-input flag. Returns "" with provided=false when no source
// is given at all.
func textFromSources(src textSources) (text string, provided bool, err error) {
	type source struct {
		name    string
		resolve func() (string, error)
	}
	var sources []source
	if positional := strings.Join(src.positional, " "); strings.TrimSpace(positional) != "" {
		sources = append(sources, source{fmt.Sprintf("positional text %q", positional), func() (string, error) {
			return positional, nil
		}})
	}
	if src.stdin != nil {
		sources = append(sources, source{"--stdin", func() (string, error) {
			content, err := io.ReadAll(src.stdin)
			if err != nil {
				return "", fmt.Errorf("reading from stdin: %w", err)
			}
			return strings.TrimRight(string(content), "\r\n"), nil
		}})
	}
	if src.filePath != "" {
		sources = append(sources, source{"--file", func() (string, error) {
			// Verbatim, like every other file-input flag (--body-file,
			// --design-file, --reason-file): a file is a deliberate payload,
			// so its trailing newlines are preserved.
			return readBodyFile(src.filePath)
		}})
	}
	if src.flagSet || src.flagText != "" {
		sources = append(sources, source{src.flagName, func() (string, error) {
			return src.flagText, nil
		}})
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped cause (%w) to identify the actual stdin I/O failure and fix the upstream producer or pipe.
  2. Verify stdin is available and connected: pipe content explicitly (echo "text" | bd ... --stdin) instead of relying on inherited stdin.
  3. In scripts/CI, redirect stdin explicitly from a file: bd ... --stdin < input.txt.
  4. If stdin may be absent, pass the text positionally or via --file instead of --stdin.

Example fix

// before
cat notes.txt | bd create "title" --stdin   # fails if cat fails mid-stream
// after
bd create "title" --stdin < notes.txt       # explicit, fail-fast redirect
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure stdin has data before piping
if [ -t 0 ]; then echo "no stdin provided" >&2; exit 1; fi

Try / catch

// Go-style wrap inspection (bd source behavior)
if _, err := textFromSources(...); err != nil {
    var perr *os.PathError
    if errors.As(err, &perr) { /* handle stdin I/O failure */ }
    return fmt.Errorf("stdin input failed: %w", err)
}

Prevention

When it happens

Trigger: Running a bd command with --stdin where io.ReadAll(os.Stdin) returns an error, e.g. stdin is closed by the parent process, a pipe breaks (upstream command exited), or an I/O error occurs on a redirected file descriptor.

Common situations: Piping from a command that failed mid-stream (e.g. `some-cmd | bd create --stdin` where some-cmd crashed); running in environments with no usable stdin (CI jobs, detached processes, daemons); redirecting stdin from an unreadable or deleted file.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/4034d3acd8ed6cce. Report an issue: GitHub.