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

  1. Before setting, call GetPixelFormat(hdc): if it returns nonzero, reuse that id (DescribePixelFormat on it) and skip SetPixelFormat entirely
  2. Create a fresh HWND when a different pixel format is genuinely required
  3. 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

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


AI-assisted analysis of wezterm/wezterm@3ff7522b96 (2026-08-20). Data as JSON: /api/errors/b76d1711c08d8f19. Report an issue: GitHub.