plandex-ai/plandex · error
failed to open keyboard: %s
Error message
failed to open keyboard: %s
What it means
GetUserKeyInput wraps failures from the eiannone/keyboard library when putting the terminal into raw mode (keyboard.Open). Without raw mode the library cannot read single keystrokes, so confirm-style prompts cannot function.
Source
Thrown at app/cli/term/prompt.go:73
return res, nil
}
func GetUserPasswordInput(msg string) (string, error) {
disableBracketedPaste()
defer enableBracketedPaste()
res, err := prompt.New().Ask(msg).Input("", input.WithEchoMode(input.EchoPassword))
if err != nil && err.Error() == "user quit prompt" {
os.Exit(0)
}
return res, err
}
func GetUserKeyInput() (rune, keyboard.Key, error) {
if err := keyboard.Open(); err != nil {
return 0, 0, fmt.Errorf("failed to open keyboard: %s", err)
}
defer func() {
_ = keyboard.Close()
}()
char, key, err := keyboard.GetKey()
if err != nil {
return 0, 0, fmt.Errorf("failed to read keypress: %s", err)
}
return char, key, nil
}
func ConfirmYesNo(fmtStr string, fmtArgs ...interface{}) (bool, error) {
color.New(ColorHiMagenta, color.Bold).Printf(fmtStr+" (y)es | (n)o", fmtArgs...)
color.New(ColorHiMagenta, color.Bold).Print("> ")
char, key, err := GetUserKeyInput()View on GitHub (pinned to e2d772072e)
Solutions
- Run the command in a standard interactive terminal (xterm, iTerm, Windows Terminal)
- Ensure stdin is a real TTY, not a pipe or /dev/null
- On Windows, use a terminal that supports console input or a build with proper console support
- Avoid running confirm-prompt commands under non-interactive automation; use flags that skip prompts
Example fix
// before printf "n\n" | plandex apply // after plandex apply --yes # or run interactively and press y/n
Defensive patterns
Strategy: fallback
Validate before calling
fi, _ := os.Stdin.Stat() ttyOK := (fi.Mode() & os.ModeCharDevice) != 0 // if false, keyboard.Open will likely fail
Try / catch
char, key, err := term.GetUserKeyInput()
if err != nil {
// fallback: read a full line from a buffered reader instead of raw keyboard
line, _ := bufio.NewReader(os.Stdin).ReadString('\n')
key = normalizeToKey(line)
} Prevention
- Avoid raw-keyboard prompts in CI/scripts; use flag-based answers
- Use standard terminals (iTerm2, Windows Terminal, xterm)
- Test commands with piped stdin locally to catch non-TTY paths early
When it happens
Trigger: keyboard.Open() fails: stdin is not a TTY, the terminal can't be switched to raw mode (restricted environment, Windows console without cgo build of the lib, unsupported terminal), or the device file can't be opened.
Common situations: Running commands under piped stdin in CI, inside some IDE terminals or Windows shells lacking console support, or in sandboxed/container environments without a TTY.
Related errors
- failed to read keypress: %s
- error selecting account: %v
- failed to get confirmation user input: %s
- error confirming: %v
- failed to create glamour renderer: %w
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/82d197d27be22305.
Report an issue: GitHub.