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
- Ensure the overlay only runs on Windows with GPUI's Win32 (winit/Win32) backend and a real, visible window.
- Check that the window passed to `show` was created by the platform window path, not a mock or test stub.
- Upgrade/align GPUI versions so `window_handle()` returns the Win32 variant on Windows.
- 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
- Only invoke the Windows overlay path on real Win32-backed GPUI windows
- Cfg-gate platform-native window manipulation as the codebase does elsewhere
- Keep GPUI versions aligned across workspace crates so raw-handle variants match expectations
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)