charmbracelet/bubbletea · error
error getting terminal state: %w
Error message
error getting terminal state: %w
What it means
On Windows, after input setup, initInput() saves the output screen buffer state with term.GetState(p.ttyOutput.Fd()) so it can be restored when the program exits. This error means that snapshot failed — the output handle is not a readable console screen buffer at that moment. Program.Run() aborts because Bubble Tea cannot guarantee it can restore the user's terminal afterwards.
Source
Thrown at tty_windows.go:40
}
// Enable VT input
var mode uint32
if err := windows.GetConsoleMode(windows.Handle(p.ttyInput.Fd()), &mode); err != nil {
return fmt.Errorf("error getting console mode: %w", err)
}
if err := windows.SetConsoleMode(windows.Handle(p.ttyInput.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
return fmt.Errorf("error setting console mode: %w", err)
}
}
// Save output screen buffer state and enable VT processing.
if f, ok := p.output.(term.File); ok && term.IsTerminal(f.Fd()) {
p.ttyOutput = f
p.previousOutputState, err = term.GetState(f.Fd())
if err != nil {
return fmt.Errorf("error getting terminal state: %w", err)
}
var mode uint32
if err := windows.GetConsoleMode(windows.Handle(p.ttyOutput.Fd()), &mode); err != nil {
return fmt.Errorf("error getting console mode: %w", err)
}
if err := windows.SetConsoleMode(windows.Handle(p.ttyOutput.Fd()),
mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|
windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
return fmt.Errorf("error setting console mode: %w", err)
}
//nolint:godox
// TODO: check if we can optimize cursor movements on Windows.
p.checkOptimizedMovements(p.previousOutputState)
}
View on GitHub (pinned to 351d2159f8)
Solutions
- Ensure the output handle stays a live console screen buffer for the whole run — do not close the ConPTY until Program.Run() returns.
- If output is genuinely redirected, pass the actual writer via tea.WithOutput(w) (or nil) instead of letting the program inherit a half-valid handle.
- Run from a normal interactive console session to confirm the code path works before blaming configuration.
- For headless runs, tea.WithoutRenderer() skips this initialization entirely.
Example fix
// before
f, _ := os.OpenFile("out.log", os.O_WRONLY, 0o644)
p := tea.NewProgram(model{}, tea.WithOutput(f)) // later state save fails on dead handle
// after: keep exactly one stable output target for the program lifetime
p := tea.NewProgram(model{}, tea.WithOutput(os.Stdout)) Defensive patterns
Strategy: validation
Validate before calling
if f, ok := os.Stdout.(term.File); ok && !term.IsTerminal(f.Fd()) {
// stdout cannot be snapshotted/restored; run headless
p := tea.NewProgram(model, tea.WithoutRenderer(), tea.WithOutput(nil))
} Type guard
func isConsoleScreenBuffer(f term.File) bool {
var mode uint32
return windows.GetConsoleMode(windows.Handle(f.Fd()), &mode) == nil
} Try / catch
if _, err := p.Run(); err != nil {
if strings.Contains(err.Error(), "error getting terminal state") {
log.Fatal("stdout is not a live console screen buffer; keep the output handle stable or run with tea.WithoutRenderer()")
}
log.Fatalf("run: %v", err)
} Prevention
- Give the program one stable output target for its whole lifetime; do not swap or close stdout mid-run.
- Keep test ConPTY output handles open until the program exits.
- Validate the output handle with GetConsoleMode before p.Run() when embedding in unusual hosts.
When it happens
Trigger: Program output implements term.File and passes term.IsTerminal(), but GetState's internal GetConsoleMode on the screen buffer fails: the output handle was closed/replaced between the IsTerminal check and the call, or the handle points to a non-console sink that was misdetected.
Common situations: A harness or parent process swapping/closing the ConPTY output handle during startup, piping stdout while a wrapper pty still makes it look like a terminal, and services started with redirected-but-then-detached output.
Related errors
- error making terminal raw: %w
- error getting console mode: %w
- error entering raw mode: %w
- error setting console mode: %w
- bubbletea: error opening TTY: %w
AI-assisted analysis of charmbracelet/bubbletea@351d2159f8 (2026-08-15).
Data as JSON: /api/errors/cc0906c57fc5cb0c.
Report an issue: GitHub.