AprilNEA/OpenLogi · error

ring window has no Win32 handle

Error message

ring window has no Win32 handle

What it means

The Windows overlay's `show` obtains the ring window's raw handle via the windowing crate and requires the `RawWindowHandle::Win32` variant, since the DPI-bootstrap trick needs a real HWND. If GPUI hands back any other raw-handle variant, the code cannot proceed on Windows and bails with this error.

Solutions

  1. Ensure the overlay only runs on Windows with GPUI's Win32 (winit/Win32) backend and a real, visible window.
  2. Check that the window passed to `show` was created by the platform window path, not a mock or test stub.
  3. Upgrade/align GPUI versions so `window_handle()` returns the Win32 variant on Windows.
  4. If supporting other platforms in this file, cfg-gate the Win32 path as the codebase does elsewhere.

Example fix

// before
let RawWindowHandle::Win32(handle) = window.window_handle()?.as_raw() else {
    anyhow::bail!("ring window has no Win32 handle");
};
// after (guard the platform before showing)
#[cfg(target_os = "windows")]
let handle = match window.window_handle()?.as_raw() {
    RawWindowHandle::Win32(h) => h,
    other => anyhow::bail!("ring window has no Win32 handle, got {other:?}"),
};
Defensive patterns

Strategy: try-catch

Type guard

fn is_win32_handle(handle: &RawWindowHandle) -> bool {
    matches!(handle, RawWindowHandle::Win32(_))
}

Try / catch

match show(&mut window) {
    Err(e) if e.to_string().contains("no Win32 handle") => {
        log::error!("overlay requires a Win32-backed window on Windows: {e}");
    }
    Err(e) => log::error!("overlay show failed: {e}"),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Calling `show` on a ring window whose `window_handle().as_raw()` is not `RawWindowHandle::Win32` — i.e. the window is not backed by Win32 (wrong platform build, headless/mock window, or a GPUI backend change).

Common situations: Running or testing the Windows overlay path with a window created by a non-Win32 backend; a GPUI version change altering the raw-handle variant; mixing platform code so the overlay runs off-Windows where Win32 handles don't exist.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13). Data as JSON: /api/errors/53aedf3c80cbd87a. Report an issue: GitHub.

Appendix: source

Thrown at crates/openlogi-overlay/src/platform/windows/native.rs:76

                point(DevicePixels(cursor.x), DevicePixels(cursor.y))
            } else {
                display.center()
            },
            display,
        })
    }

    #[expect(
        unsafe_code,
        reason = "borrow the live GPUI HWND on its owning UI thread"
    )]
    pub(crate) fn show(self, window: &mut Window) -> Result<()> {
        let RawWindowHandle::Win32(handle) = window
            .window_handle()
            .map_err(|error| anyhow::anyhow!("get ring HWND: {error}"))?
            .as_raw()
        else {
            anyhow::bail!("ring window has no Win32 handle");
        };
        let hwnd = handle.hwnd.get() as HWND;
        // Bootstrap a tiny hidden window well inside the selected monitor.
        // SetWindowPos synchronously delivers WM_DPICHANGED; GPUI applies its
        // suggested rectangle and updates rendering scale before this returns.
        // Final geometry is applied only AFTER that transition, so the suggested
        // rectangle cannot move a cursor-centred ring away from its anchor.
        let anchor = Bounds::new(
            self.display.center(),
            size(DevicePixels(1), DevicePixels(1)),
        );
        set_bounds(hwnd, anchor, SWP_NOACTIVATE | SWP_NOZORDER)?;
        // SAFETY: hwnd belongs to the still-borrowed window.
        let dpi = unsafe { GetDpiForWindow(hwnd) };
        ensure!(dpi != 0, "could not read ring window DPI");
        // SAFETY: read-only query on the still-borrowed window.
        let monitor = unsafe { MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) };
        ensure!(

View on GitHub (pinned to e846e6f4b4)