wezterm/wezterm · error
SetPixelFormat function failed: {}
Error message
SetPixelFormat function failed: {} What it means
SetPixelFormat returned 0 applying the chosen format to the window's DC. The classic cause: on Windows an HDC's pixel format can be set only once for the lifetime of the window — a second SetPixelFormat on the same HWND/DC fails. Also triggered by invalid hdc/format ids, or formats owned by a different driver.
Source
Thrown at window/src/os/windows/wgl.rs:281
let res = unsafe {
DescribePixelFormat(
hdc,
format_id,
std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as _,
&mut pfd,
)
};
if res == 0 {
anyhow::bail!(
"DescribePixelFormat function failed: {}",
std::io::Error::last_os_error()
);
}
let res = unsafe { SetPixelFormat(hdc, format_id, &pfd) };
if res == 0 {
anyhow::bail!(
"SetPixelFormat function failed: {}",
std::io::Error::last_os_error()
);
}
let mut attribs = vec![
CONTEXT_MAJOR_VERSION_ARB as i32,
4,
CONTEXT_MINOR_VERSION_ARB as i32,
5,
CONTEXT_PROFILE_MASK_ARB as i32,
CONTEXT_CORE_PROFILE_BIT_ARB as i32,
];
if has_extension(&extensions, "WGL_ARB_create_context_robustness") {
log::trace!("requesting robustness features");
attribs.push(CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as i32);
attribs.push(LOSE_CONTEXT_ON_RESET_ARB as i32);View on GitHub (pinned to 3ff7522b96)
Solutions
- Before setting, call GetPixelFormat(hdc): if it returns nonzero, reuse that id (DescribePixelFormat on it) and skip SetPixelFormat entirely
- Create a fresh HWND when a different pixel format is genuinely required
- Ensure only one component owns GL initialization per window
Example fix
// before
let res = unsafe { SetPixelFormat(hdc, format_id, &pfd) };
if res == 0 {
anyhow::bail!("SetPixelFormat function failed: {}", std::io::Error::last_os_error());
}
// after
let existing = unsafe { GetPixelFormat(hdc) };
if existing == 0 {
let res = unsafe { SetPixelFormat(hdc, format_id, &pfd) };
if res == 0 {
anyhow::bail!("SetPixelFormat function failed: {}", std::io::Error::last_os_error());
}
} // else: format already fixed for this window; reuse it Defensive patterns
Strategy: validation
Validate before calling
// Respect the one-format-per-window rule before setting
let existing = unsafe { GetPixelFormat(hdc) };
if existing != 0 {
// format already chosen for this window: describe and reuse it
let mut pfd: PIXELFORMATDESCRIPTOR = unsafe { std::mem::zeroed() };
unsafe { DescribePixelFormat(hdc, existing, std::mem::size_of::<PIXELFORMATDESCRIPTOR>() as _, &mut pfd) };
return Ok(existing);
} Try / catch
let res = unsafe { SetPixelFormat(hdc, format_id, &pfd) };
if res == 0 {
let e = std::io::Error::last_os_error();
if e.raw_os_error() == Some(2000) /* ERROR_INVALID_PIXEL_FORMAT */ || unsafe { GetPixelFormat(hdc) } != 0 {
// already set: reuse the existing format instead of failing
return Ok(unsafe { GetPixelFormat(hdc) });
}
anyhow::bail!("SetPixelFormat function failed: {e}");
} Prevention
- Remember SetPixelFormat succeeds only once per HWND/DC: design re-init to reuse, not re-set
- Create a new window when a different pixel format is truly required
- Have exactly one owner of GL initialization per window to avoid racing setters
When it happens
Trigger: Calling enable_opengl a second time on the same window (re-init, reconnect, pane respawn) after the pixel format was already set; two code paths racing to initialize GL on one window; keeping a cached DC after the format was applied elsewhere.
Common situations: Recreating a GL context after context loss without creating a new window; multiple renderers attaching to one surface; teardown/reinit cycles in long-running apps.
Related errors
- ChoosePixelFormatARB returned 0
- ChoosePixelFormatARB returned 0 formats
- DescribePixelFormat function failed: {}
- CreateWindowExW: {}
- CreateContextAttribsARB failed, GetLastError={} {:x}
AI-assisted analysis of wezterm/wezterm@3ff7522b96 (2026-08-20).
Data as JSON: /api/errors/b76d1711c08d8f19.
Report an issue: GitHub.