{"record":{"id":"f3d6f92b3f8a0f2d","repo":"charmbracelet/bubbletea","slug":"bubbletea-error-writing-to-screen-w","errorCode":null,"errorMessage":"bubbletea: error writing to screen: %w","messagePattern":"bubbletea: error writing to screen: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cursed_renderer.go","lineNumber":231,"sourceCode":"\t\t\t_, _ = s.scr.WriteString(ansi.ResetProgressBar)\n\t\t}\n\t}\n\n\tif s.cellbuf.Method == ansi.GraphemeWidth {\n\t\t// Make sure to turn off Unicode mode (2027)\n\t\t_, _ = s.scr.WriteString(ansi.ResetModeUnicodeCore)\n\t}\n\n\tif err := s.scr.Flush(); err != nil {\n\t\treturn fmt.Errorf(\"bubbletea: error closing screen writer: %w\", err)\n\t}\n\n\tif s.buf.Len() > 0 {\n\t\tif s.logger != nil {\n\t\t\ts.logger.Printf(\"output: %q\", s.buf.String())\n\t\t}\n\t\tif _, err := io.Copy(s.w, &s.buf); err != nil {\n\t\t\treturn fmt.Errorf(\"bubbletea: error writing to screen: %w\", err)\n\t\t}\n\t\ts.buf.Reset()\n\t}\n\n\tx, y := s.scr.Position()\n\n\t// We want to clear the renderer state but not the cursor position. This is\n\t// because we might be putting the tea process in the background, run some\n\t// other process, and then return to the tea process. We want to keep the\n\t// cursor position so that we can continue where we left off.\n\treset(s)\n\ts.scr.SetPosition(x, y)\n\n\treturn nil\n}\n\n// writeString implements renderer.\nfunc (s *cursedRenderer) writeString(str string) (int, error) {","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/charmbracelet/bubbletea/blob/351d2159f8d8a85613aa2a6e98c8c63df3c98623/cursed_renderer.go#L213-L249","documentation":"Returned during renderer close when the buffered output (s.buf) could not be copied to the destination writer (s.w) with io.Copy after the screen flush. This is the last-chance write of remaining rendered content at teardown; failing here means the final frame or reset bytes never reached the terminal. The error wraps the underlying write error (often EPIPE, ErrClosed, or an IO timeout).","triggerScenarios":"io.Copy(s.w, &s.buf) failing during renderer close: destination writer closed, broken pipe, pty gone, or a custom tea.WithOutput writer returning an error. Happens after a render cycle buffered content that was never delivered.","commonSituations":"Output piped to a process that exited (`| head`); terminal window closed while the program is shutting down; custom output writer (network socket, bytes.Buffer wrapper) returning errors; CI environments where stdout detaches mid-run.","solutions":["Keep the output writer open for the entire lifetime of the program, closing it only after Run returns","For non-interactive runs use tea.WithoutRenderer() so no screen writes are attempted","Debounce or retry if writing to a flaky custom writer; make your writer return clearer errors","If the pipe consumer exiting early is expected, ignore ErrClosed/EPIPE on shutdown"],"exampleFix":"// before\nw := getWriter() // may be closed by another goroutine\np := tea.NewProgram(m, tea.WithOutput(w))\n_, err := p.Run()\n\n// after\nw := getWriter()\np := tea.NewProgram(m, tea.WithOutput(w))\n_, _ = p.Run() // consume remaining writes first\nw.Close()      // close only afterwards","handlingStrategy":"fallback","validationCode":"// Keep ownership discipline: close output after Run\ndone := make(chan struct{})\ngo func() { defer close(done); p.Run() }()\n// ... later: <-done; w.Close()","typeGuard":"func benignWriteFailure(err error) bool {\n    return errors.Is(err, os.ErrClosed) || errors.Is(err, syscall.EPIPE) || errors.Is(err, io.EOF)\n}","tryCatchPattern":"_, err := p.Run()\nif err != nil && strings.Contains(err.Error(), \"error writing to screen\") {\n    if benignWriteFailure(errors.Unwrap(errors.Unwrap(err))) { err = nil }\n}","preventionTips":["Never close stdout-equivalent writers concurrently with Run","In pipelines, exit early via p.Quit when the consumer dies","Use WithoutRenderer for headless automation","Log but don't crash on shutdown-time write failures"],"tags":["bubbletea","renderer","io","write","shutdown","go"],"backgroundTag":null,"analyzedSha":"351d2159f8d8a85613aa2a6e98c8c63df3c98623","analyzedAt":"2026-08-15T10:48:22.366Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}