charmbracelet/gum · error
failed to write to stdout: %w
Error message
failed to write to stdout: %w
What it means
When the action run by gum spin fails (m.err != nil), the error is printed to stderr; if even that Fprintf to stderr fails, Run returns this misleadingly-worded 'failed to write to stdout' wrapper. It signals the process cannot write to standard streams at all.
Source
Thrown at spin/command.go:56
defer cancel()
tm, err := tea.NewProgram(
m,
tea.WithOutput(os.Stderr),
tea.WithContext(ctx),
tea.WithInput(nil),
).Run()
if err != nil {
return fmt.Errorf("unable to run action: %w", err)
}
m = tm.(model)
// If the command succeeds, and we are printing output and we are in a TTY then push the STDOUT we got to the actual
// STDOUT for piping or other things.
//nolint:nestif
if m.err != nil {
if _, err := fmt.Fprintf(os.Stderr, "%s\n", m.err.Error()); err != nil {
return fmt.Errorf("failed to write to stdout: %w", err)
}
return exit.ErrExit(1)
} else if m.status == 0 {
var output string
if o.ShowOutput || (o.ShowStdout && o.ShowStderr) {
output = m.output
} else if o.ShowStdout {
output = m.stdout
} else if o.ShowStderr {
output = m.stderr
}
if output != "" {
if _, err := os.Stdout.WriteString(output); err != nil {
return fmt.Errorf("failed to write to stdout: %w", err)
}
}
} else if o.ShowError {
// Otherwise if we are showing errors and the command did not exit with a 0 status code then push all of the commandView on GitHub (pinned to 4d089f9550)
Solutions
- Fix the underlying action error (printed via m.err) first — that's the real failure.
- Ensure stderr is open/attached when running gum spin (don't redirect it to a closed descriptor).
- Check disk space and file descriptor limits.
- Handle SIGPIPE/broken-pipe semantics in the surrounding pipeline.
Example fix
// before (stderr closed) gum spin -- ./build.sh 2>&- // after gum spin -- ./build.sh 2>spin.log
Defensive patterns
Strategy: try-catch
Try / catch
if ! gum spin -- ./build.sh 2>spin.err; then cat spin.err >&2; fi # keep stderr open and capture the real action error
Prevention
- Never close or redirect stderr to a closed descriptor
- Keep stderr attached in containers
- Monitor disk space in long-running jobs
- Read the wrapped action error first — it is the real cause
When it happens
Trigger: m.err set by the spin action AND the subsequent fmt.Fprintf(os.Stderr, ...) returning an error — e.g. closed/broken stderr pipe (`cmd 2>&- | ...`), full disk, or a broken pipe on the receiving end.
Common situations: Shell pipelines that closed stderr; containers with no stderr attached; disk-full conditions while a long spin action failed.
Related errors
- unable to write output: %w
- stdin is empty
- failed to read line: %w
- failed to write col %d of selected row: %w
- failed to write selected row: %w
AI-assisted analysis of charmbracelet/gum@4d089f9550 (2026-08-31).
Data as JSON: /api/errors/fa2a657a11757b37.
Report an issue: GitHub.