{"record":{"id":"ae28b3bf38505664","repo":"charmbracelet/bubbletea","slug":"bubbletea-error-getting-terminal-size-w","errorCode":null,"errorMessage":"bubbletea: error getting terminal size: %w","messagePattern":"bubbletea: error getting terminal size: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tea.go","lineNumber":1047,"sourceCode":"\t\t\t\treturnErr = fmt.Errorf(\"%w: %w\", ErrProgramKilled, ErrProgramPanic)\n\t\t\t\tp.recoverFromPanic(r)\n\t\t\t}\n\t\t}()\n\t}\n\n\t// Check if output is a TTY before entering raw mode, hiding the cursor and\n\t// so on.\n\tif err := p.initTerminal(); err != nil {\n\t\treturn p.initialModel, err\n\t}\n\n\t// Get the initial window size.\n\twidth, height := p.width, p.height\n\tif p.ttyOutput != nil {\n\t\t// Set the initial size of the terminal.\n\t\tw, h, err := term.GetSize(p.ttyOutput.Fd())\n\t\tif err != nil {\n\t\t\treturn p.initialModel, fmt.Errorf(\"bubbletea: error getting terminal size: %w\", err)\n\t\t}\n\n\t\twidth, height = w, h\n\t}\n\n\tp.width, p.height = width, height\n\tresizeMsg := WindowSizeMsg{Width: p.width, Height: p.height}\n\n\tif p.renderer == nil {\n\t\tif p.disableRenderer {\n\t\t\tp.renderer = &nilRenderer{}\n\t\t} else {\n\t\t\t// If no renderer is set use the cursed one.\n\t\t\tr := newCursedRenderer(\n\t\t\t\tp.output,\n\t\t\t\tp.environ,\n\t\t\t\tp.width,\n\t\t\t\tp.height,","sourceCodeStart":1029,"sourceCodeEnd":1065,"githubUrl":"https://github.com/charmbracelet/bubbletea/blob/351d2159f8d8a85613aa2a6e98c8c63df3c98623/tea.go#L1029-L1065","documentation":"Returned by Program.Run right after terminal init when term.GetSize on the output TTY file descriptor fails, so Bubble Tea cannot learn the initial terminal dimensions to size the first frame. The wrapped error is typically an ioctl (TIOCGWINSZ) failure such as EINVAL or ENOTTY. Program startup aborts and the terminal state is restored.","triggerScenarios":"Output is a TTY-like handle that doesn't support the window-size ioctl (some ptys mid-teardown, closed fds, serial consoles); output set via tea.WithOutput to a file/socket that passed TTY checks but fails TIOCGWINSZ; terminal emulator in a transient state during startup; fd limit issues.","commonSituations":"Running under a half-configured pty in tests; output redirected to /dev/null on some platforms; running inside certain CI pseudo-terminals or `script` wrappers; race between terminal creation and program start; exotic environments (jails, containers) with limited ioctls.","solutions":["If output is not a real terminal, pass tea.WithOutput(io.Discard) or os.Stdout with tea.WithoutRenderer()","Set an explicit initial size with tea.WithWindowSize? no — instead pre-set via Program options like tea.WithAltScreen is unrelated: use p's width/height by constructing with tea.WithInput... ultimately: avoid fake TTYs; run inside a real terminal or real pty (e.g. creack/pty in tests)","Retry starting the program after a short delay if the terminal was mid-initialization","Check the wrapped errno: ENOTTY means non-terminal output — switch to non-renderer mode"],"exampleFix":"// before\np := tea.NewProgram(m, tea.WithOutput(f)) // f: not a real tty, ioctl fails\n_, err := p.Run()\n\n// after\nif term.IsTerminal(f.Fd()) {\n    p := tea.NewProgram(m, tea.WithOutput(f))\n    _, err = p.Run()\n} else {\n    p := tea.NewProgram(m, tea.WithoutRenderer(), tea.WithOutput(f))\n    _, err = p.Run()\n}","handlingStrategy":"validation","validationCode":"// Validate the output fd supports window-size queries before Run:\nfunc supportsWINSZ(f *os.File) bool {\n    _, _, err := term.GetSize(f.Fd())\n    return err == nil\n}\nif !supportsWINSZ(out) {\n    p := tea.NewProgram(m, tea.WithoutRenderer(), tea.WithOutput(out))\n    // ... run in plain mode\n}","typeGuard":"func isGetSizeFailure(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"error getting terminal size\")\n}","tryCatchPattern":"_, err := p.Run()\nif isGetSizeFailure(err) {\n    if errors.Is(errors.Unwrap(err), syscall.ENOTTY) {\n        // fall back to renderer-less mode\n        _, err = tea.NewProgram(m, tea.WithoutRenderer()).Run()\n    }\n}\nif err != nil { log.Fatal(err) }","preventionTips":["Use a real terminal or a real pty in integration tests","Don't point tea.WithOutput at files/sockets and expect TUI behavior","Retry once shortly after login/pty setup races","Prefer os.Stdout directly in normal CLI usage"],"tags":["bubbletea","tty","ioctl","window-size","startup","go"],"backgroundTag":null,"analyzedSha":"351d2159f8d8a85613aa2a6e98c8c63df3c98623","analyzedAt":"2026-08-15T10:48:22.366Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}