{"record":{"id":"553c94fd895e6a50","repo":"charmbracelet/bubbletea","slug":"error-getting-console-mode-w","errorCode":null,"errorMessage":"error getting console mode: %w","messagePattern":"error getting console mode: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tty_windows.go","lineNumber":27,"sourceCode":"\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 {\n\t\t\treturn fmt.Errorf(\"error getting terminal state: %w\", err)\n\t\t}\n\n\t\tvar mode uint32\n\t\tif err := windows.GetConsoleMode(windows.Handle(p.ttyOutput.Fd()), &mode); err != nil {\n\t\t\treturn fmt.Errorf(\"error getting console mode: %w\", err)","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/charmbracelet/bubbletea/blob/351d2159f8d8a85613aa2a6e98c8c63df3c98623/tty_windows.go#L9-L45","documentation":"After raw mode succeeded, the Windows initInput() path reads the console input mode with windows.GetConsoleMode on stdin before enabling ENABLE_VIRTUAL_TERMINAL_INPUT. This error means that read failed — the handle is no longer a valid console input buffer between the MakeRaw and GetConsoleMode calls. It aborts Program.Run().","triggerScenarios":"Called immediately after term.MakeRaw(p.ttyInput.Fd()) succeeds; fails when the console handle is invalidated concurrently (window closed, ConPTY terminated, handle freed by a parent process) or when fd conversion yields an invalid windows.Handle.","commonSituations":"A test harness or parent process closes the ConPTY while the program is starting, a scheduler/service context with a half-attached console, and races during process shutdown (Ctrl+C while the program initializes).","solutions":["Reproduce with a plain interactive console first — if it only fails under your harness, the harness is closing or detaching the console handle.","Keep the ConPTY alive for the whole Program.Run() lifetime in integration tests (do not close the pty right after spawning).","Defer program start until the console is fully attached (e.g. after windows.FreeConsole/AttachConsole sequences complete).","As a fallback for non-interactive runs, use tea.WithInput(nil) plus tea.WithoutRenderer()."],"exampleFix":"// before: test closes the pty immediately after starting the program\ngo func() { p.Run() }()\npty.Close() // console handle invalidated mid-init -> error getting console mode\n\n// after: keep the pty alive until the program exits\ndone := make(chan struct{})\ngo func() { defer close(done); p.Run() }()\n<-done\npty.Close()","handlingStrategy":"try-catch","validationCode":"var mode uint32\nif err := windows.GetConsoleMode(windows.Handle(os.Stdin.Fd()), &mode); err != nil {\n    // handle will also fail inside initInput; skip terminal mode\n    p := tea.NewProgram(model, tea.WithInput(nil))\n}","typeGuard":"func validConsoleHandle(fd uintptr) bool {\n    var mode uint32\n    return windows.GetConsoleMode(windows.Handle(fd), &mode) == nil\n}","tryCatchPattern":"if _, err := p.Run(); err != nil {\n    if strings.Contains(err.Error(), \"error getting console mode\") && runtime.GOOS == \"windows\" {\n        // stdin console handle died mid-init: fix the harness that closes the ConPTY early\n        log.Fatal(\"console input handle invalidated during startup; keep the ConPTY open for the program lifetime\")\n    }\n    log.Fatalf(\"run: %v\", err)\n}","preventionTips":["In ConPTY harnesses, close the pty only after Program.Run() returns, never right after spawning.","Avoid closing or detaching stdin's console while the program initializes.","Probe the handle with GetConsoleMode immediately before p.Run() to catch dead handles early with a clear message."],"tags":["windows","console","conpty","handle","bubbletea","initialization"],"backgroundTag":null,"analyzedSha":"351d2159f8d8a85613aa2a6e98c8c63df3c98623","analyzedAt":"2026-08-15T10:48:22.366Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}