BigPizzaV3/CodexPlusPlus · error · anyhow::Error

SetThreadDpiAwarenessContext failed

Error message

SetThreadDpiAwarenessContext failed

What it means

windows_logical_cursor_position (crates/codex-plus-core/src/launcher.rs:1390, compiled only on Windows) temporarily switches the thread's DPI awareness to DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED before GetCursorPos so coordinates come back in unscaled pixels for the overlay feature. SetThreadDpiAwarenessContext returns null when it fails (its return is the previous context); the code treats null as failure and bails. The API requires Windows 10 1703+, so unsupported older OSes and certain thread/host environments are the practical causes.

Source

Thrown at crates/codex-plus-core/src/launcher.rs:1396

            bytes,
            content_type.to_string(),
            "helper.dream_skin_image_ok",
        ),
        Err(_) => not_found(),
    }
}

#[cfg(windows)]
fn windows_logical_cursor_position() -> anyhow::Result<(i32, i32)> {
    use windows::Win32::Foundation::POINT;
    use windows::Win32::UI::HiDpi::{
        DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED, SetThreadDpiAwarenessContext,
    };
    use windows::Win32::UI::WindowsAndMessaging::GetCursorPos;

    let previous = unsafe { SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED) };
    if previous.0.is_null() {
        anyhow::bail!("SetThreadDpiAwarenessContext failed");
    }
    let mut point = POINT::default();
    let result = unsafe { GetCursorPos(&mut point) };
    unsafe {
        SetThreadDpiAwarenessContext(previous);
    }
    result.ok().context("GetCursorPos failed")?;
    Ok((point.x, point.y))
}

fn overlay_image_content_type(path: &Path) -> Option<&'static str> {
    match path
        .extension()
        .and_then(|extension| extension.to_str())
        .map(str::to_ascii_lowercase)
        .as_deref()
    {
        Some("png") => Some("image/png"),

View on GitHub (pinned to 1f431ae49b)

Solutions

  1. Run on Windows 10 1703+ where SetThreadDpiAwarenessContext exists and succeeds
  2. Update the windows crate — newer windows-rs versions expose SetThreadDpiAwarenessContextCompat and friends that fall back correctly on older OSes
  3. If you fork the core, degrade gracefully: on null previous context, fall back to GetCursorPos without the DPI switch (coordinates will be scaled, but the call succeeds)
  4. Disable the overlay feature that needs logical cursor positions if the host cannot support DPI queries

Example fix

// before (crates/codex-plus-core/src/launcher.rs)
let previous = unsafe { SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED) };
if previous.0.is_null() {
    anyhow::bail!("SetThreadDpiAwarenessContext failed");
}

// after: tolerate unsupported DPI switch
let previous = unsafe { SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED) };
let dpi_switched = !previous.0.is_null();
let mut point = POINT::default();
let result = unsafe { GetCursorPos(&mut point) };
if dpi_switched { unsafe { SetThreadDpiAwarenessContext(previous); } }
Defensive patterns

Strategy: fallback

Validate before calling

// Probe support before relying on the overlay path
#[cfg(windows)]
fn dpi_awareness_supported() -> bool {
    use windows::Win32::UI::HiDpi::SetThreadDpiAwarenessContext;
    use windows::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED;
    let prev = unsafe { SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED) };
    let ok = !prev.0.is_null();
    if ok { unsafe { windows::Win32::UI::HiDpi::SetThreadDpiAwarenessContext(prev) }; }
    ok
}

Try / catch

match windows_logical_cursor_position() {
    Ok(pos) => Some(pos),
    Err(e) if e.to_string() == "SetThreadDpiAwarenessContext failed" => {
        tracing::warn!("DPI query unsupported; overlay uses scaled coordinates or is disabled");
        None // degrade to GetCursorPos without DPI switch, or disable overlay
    }
    Err(e) => { tracing::error!(%e); None }
}

Prevention

When it happens

Trigger: Invoking the overlay cursor-position path on Windows where SetThreadDpiAwarenessContext fails: pre-1703 Windows 10 / Windows 7-8.1 (API not exported or returns null), or a thread context in which the DPI-awareness switch is disallowed.

Common situations: Running the CodexPlusPlus overlay on an old or LTSC-pre-1703 Windows image; Wine/compatibility layers that stub Win32 DPI APIs; CI runners with stripped Windows shells where per-monitor DPI v2 context handling misbehaves.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16). Data as JSON: /api/errors/73c75e8e700c963f. Report an issue: GitHub.