wezterm/wezterm · error
SetConsoleMode failed: {}
Error message
SetConsoleMode failed: {} What it means
On Windows, InputHandle::set_input_mode calls SetConsoleMode on the console input handle to install the mode flags termwiz needs (raw input, virtual terminal input, etc.). The API returns 0 on failure and the code bails with GetLastError(). It fails when the handle is not a console input handle, is closed, or the mode bits are invalid for that handle type.
Source
Thrown at termwiz/src/terminal/windows.rs:92
dy: i16,
attr: u16,
) -> Result<()>;
}
struct InputHandle {
handle: FileDescriptor,
}
impl Read for InputHandle {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
self.handle.read(buf)
}
}
impl ConsoleInputHandle for InputHandle {
fn set_input_mode(&mut self, mode: u32) -> Result<()> {
if unsafe { SetConsoleMode(self.handle.as_raw_handle(), mode) } == 0 {
bail!("SetConsoleMode failed: {}", IoError::last_os_error());
}
Ok(())
}
fn get_input_mode(&mut self) -> Result<u32> {
let mut mode = 0;
if unsafe { GetConsoleMode(self.handle.as_raw_handle(), &mut mode) } == 0 {
bail!("GetConsoleMode failed: {}", IoError::last_os_error());
}
Ok(mode)
}
fn set_input_cp(&mut self, cp: u32) -> Result<()> {
if unsafe { SetConsoleCP(cp) } == 0 {
bail!("SetConsoleCP failed: {}", IoError::last_os_error());
}
Ok(())
}View on GitHub (pinned to b99b1ca2cc)
Solutions
- Run with stdin attached to a real console (interactive cmd/PowerShell/Windows Terminal)
- Verify the handle is a console before entering raw mode: call GetConsoleMode first; if it fails, redirect scenarios must be handled separately
- On Windows 10+ ensure the console supports VT; use Windows Terminal or ConPTY rather than legacy conhost
- When stdin is not a console, use a pty layer (ConPTY / portable-pty) instead of the console APIs
Defensive patterns
Strategy: validation
Validate before calling
// probe whether stdin is a console before touching console modes
let mut mode = 0u32;
let is_console = unsafe {
consoleapi::GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE) as *mut _, &mut mode)
} != 0;
if !is_console { /* use non-console input path */ } Type guard
fn is_console_handle(handle: HANDLE) -> bool {
let mut mode = 0u32;
unsafe { consoleapi::GetConsoleMode(handle as *mut _, &mut mode) } != 0
} Try / catch
if let Err(e) = input.set_input_mode(mode) {
if !is_console_handle(handle) {
// stdin is redirected: fall back to plain stream reading
return setup_non_console_input();
}
return Err(e);
} Prevention
- Probe console availability once at startup and branch to a non-console code path immediately
- Keep stdin unredirected for interactive builds; offer a --plain mode for piped runs
- Require Windows 10+ / Windows Terminal for VT-input-dependent features
When it happens
Trigger: Entering raw mode / setting input modes when stdin is redirected (pipe or file instead of the console), when the console handle was closed, when the process has no attached console (some service/session setups), or when invalid mode flag combinations are passed.
Common situations: Running a termwiz/wezterm-based TUI with stdin redirected (`app < file`), under CI on Windows without a console, detached services, or legacy consoles where VT input flags (ENABLE_VIRTUAL_TERMINAL_INPUT) are unsupported.
Related errors
- SetConsoleCP failed: {}
- ReadConsoleInput failed: {}
- SetConsoleOutputCP failed: {}
- FillConsoleOutputCharacterW failed: {}
- FillConsoleOutputAttribute failed: {}
AI-assisted analysis of wezterm/wezterm@b99b1ca2cc (2026-09-05).
Data as JSON: /api/errors/f9206751656d5223.
Report an issue: GitHub.