charmbracelet/bubbletea · error
error making terminal raw: %w
Error message
error making terminal raw: %w
What it means
The Windows counterpart of the raw-mode failure: initInput() on Windows calls term.MakeRaw() on the stdin console handle and the Win32 console API rejected it. term.MakeRaw on Windows is implemented with GetConsoleMode/SetConsoleMode on the input handle, so it fails when the handle is not a live console input buffer. The error is returned from Program.Run() and the program aborts before the first frame.
Source
Thrown at tty_windows.go:21
package tea
import (
"fmt"
"github.com/charmbracelet/x/term"
"golang.org/x/sys/windows"
)
func (p *Program) initInput() (err error) {
// Save stdin state and enable VT input
// We also need to enable VT
// input here.
if f, ok := p.input.(term.File); ok && term.IsTerminal(f.Fd()) {
p.ttyInput = f
p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd())
if err != nil {
return fmt.Errorf("error making terminal raw: %w", err)
}
// 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 {View on GitHub (pinned to 351d2159f8)
Solutions
- Run the program in a real Windows console: Windows Terminal, conhost, or PowerShell/cmd — for mintty/MSYS2/Git-Bash prefix with `winpty`.
- If stdin is not a console, pass tea.WithInput(nil) or a pipe/io.Reader instead so the IsTerminal branch is skipped entirely.
- For headless or tested runs, use tea.WithoutRenderer() to bypass initTerminal().
- Print and inspect the wrapped syscall error (ERROR_INVALID_HANDLE vs ERROR_ACCESS_DENIED) to distinguish a closed handle from a permissions problem.
Example fix
// before
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
log.Fatalf("run: %v", err) // error making terminal raw: The handle is invalid
}
// after
var in io.Reader
if f, ok := stdin.(term.File); ok && term.IsTerminal(f.Fd()) {
in = stdin // only hand over a real console
}
p := tea.NewProgram(model{}, tea.WithInput(in)) Defensive patterns
Strategy: validation
Validate before calling
if f, ok := os.Stdin.(term.File); ok && !term.IsTerminal(f.Fd()) {
// skip raw mode entirely
p := tea.NewProgram(model, tea.WithInput(nil), tea.WithoutRenderer())
_, _ = p.Run()
return
} Type guard
func isWindowsConsole(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 making terminal raw") {
// console handle is dead or emulated; run winpty or Windows Terminal, or degrade:
log.Fatal("stdin console unusable; run under a real Windows console (or prefix with winpty under mintty)")
}
log.Fatalf("run: %v", err)
} Prevention
- Run Windows builds in Windows Terminal, cmd, or PowerShell; under mintty/Git-Bash/MSYS2 always prefix with winpty.
- Branch on term.IsTerminal(os.Stdin.Fd()) before p.Run() and use tea.WithInput(nil) when there is no console.
- Do not start the program from services or GUI processes without first attaching a console.
- Keep test ConPTYs alive until Program.Run() returns.
When it happens
Trigger: Program input implements term.File and passes term.IsTerminal(), but the underlying handle fails the raw-mode transition: stdin is a closed console handle, a redirected handle that IsTerminal misidentified, or a ConPTY whose input side has already been torn down.
Common situations: Running the built .exe from a mintty/MSYS2/Git-Bash shell (mintty is not a Windows console; raw mode on its emulated tty fails without winpty), running under `go test` or a service with no attached console, double-clicking a .exe whose console closed, and older Windows builds where the console host behaves differently.
Related errors
- error entering raw mode: %w
- error getting console mode: %w
- error getting terminal state: %w
- error setting console mode: %w
- program experienced a panic
AI-assisted analysis of charmbracelet/bubbletea@351d2159f8 (2026-08-15).
Data as JSON: /api/errors/0ad54cf9a170ed1f.
Report an issue: GitHub.