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

  1. Run the program in a real Windows console: Windows Terminal, conhost, or PowerShell/cmd — for mintty/MSYS2/Git-Bash prefix with `winpty`.
  2. If stdin is not a console, pass tea.WithInput(nil) or a pipe/io.Reader instead so the IsTerminal branch is skipped entirely.
  3. For headless or tested runs, use tea.WithoutRenderer() to bypass initTerminal().
  4. 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

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


AI-assisted analysis of charmbracelet/bubbletea@351d2159f8 (2026-08-15). Data as JSON: /api/errors/0ad54cf9a170ed1f. Report an issue: GitHub.