{"record":{"id":"0ad54cf9a170ed1f","repo":"charmbracelet/bubbletea","slug":"error-making-terminal-raw-w","errorCode":null,"errorMessage":"error making terminal raw: %w","messagePattern":"error making terminal raw: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tty_windows.go","lineNumber":21,"sourceCode":"\npackage tea\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/charmbracelet/x/term\"\n\t\"golang.org/x/sys/windows\"\n)\n\nfunc (p *Program) initInput() (err error) {\n\t// Save stdin state and enable VT input\n\t// We also need to enable VT\n\t// input here.\n\tif f, ok := p.input.(term.File); ok && term.IsTerminal(f.Fd()) {\n\t\tp.ttyInput = f\n\t\tp.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd())\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error making terminal raw: %w\", err)\n\t\t}\n\n\t\t// Enable VT input\n\t\tvar mode uint32\n\t\tif err := windows.GetConsoleMode(windows.Handle(p.ttyInput.Fd()), &mode); err != nil {\n\t\t\treturn fmt.Errorf(\"error getting console mode: %w\", err)\n\t\t}\n\n\t\tif err := windows.SetConsoleMode(windows.Handle(p.ttyInput.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {\n\t\t\treturn fmt.Errorf(\"error setting console mode: %w\", err)\n\t\t}\n\t}\n\n\t// Save output screen buffer state and enable VT processing.\n\tif f, ok := p.output.(term.File); ok && term.IsTerminal(f.Fd()) {\n\t\tp.ttyOutput = f\n\t\tp.previousOutputState, err = term.GetState(f.Fd())\n\t\tif err != nil {","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/charmbracelet/bubbletea/blob/351d2159f8d8a85613aa2a6e98c8c63df3c98623/tty_windows.go#L3-L39","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\np := tea.NewProgram(model{})\nif _, err := p.Run(); err != nil {\n    log.Fatalf(\"run: %v\", err) // error making terminal raw: The handle is invalid\n}\n\n// after\nvar in io.Reader\nif f, ok := stdin.(term.File); ok && term.IsTerminal(f.Fd()) {\n    in = stdin // only hand over a real console\n}\np := tea.NewProgram(model{}, tea.WithInput(in))","handlingStrategy":"validation","validationCode":"if f, ok := os.Stdin.(term.File); ok && !term.IsTerminal(f.Fd()) {\n    // skip raw mode entirely\n    p := tea.NewProgram(model, tea.WithInput(nil), tea.WithoutRenderer())\n    _, _ = p.Run()\n    return\n}","typeGuard":"func isWindowsConsole(f term.File) bool {\n    var mode uint32\n    return windows.GetConsoleMode(windows.Handle(f.Fd()), &mode) == nil\n}","tryCatchPattern":"if _, err := p.Run(); err != nil {\n    if strings.Contains(err.Error(), \"error making terminal raw\") {\n        // console handle is dead or emulated; run winpty or Windows Terminal, or degrade:\n        log.Fatal(\"stdin console unusable; run under a real Windows console (or prefix with winpty under mintty)\")\n    }\n    log.Fatalf(\"run: %v\", err)\n}","preventionTips":["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."],"tags":["terminal","windows","console","raw-mode","bubbletea","initialization"],"backgroundTag":null,"analyzedSha":"351d2159f8d8a85613aa2a6e98c8c63df3c98623","analyzedAt":"2026-08-15T10:48:22.366Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}