LGUG2Z/komorebi · error
could not find next window
Error message
could not find next window
What it means
top_visible_window walks the z-order with GetWindow/GW_HWNDNEXT looking for the next visible top-level window. If the enumeration exhausts without finding one, komorebi bails with 'could not find next window'. It indicates no visible sibling window was reachable in the z-order chain.
Source
Thrown at komorebi/src/windows_api.rs:762
)?;
Ok(hwnds)
}
#[allow(dead_code)]
pub fn top_visible_window() -> eyre::Result<isize> {
let hwnd = Self::top_window()?;
let mut next_hwnd = hwnd;
while next_hwnd != 0 {
if Self::is_window_visible(next_hwnd) {
return Ok(next_hwnd);
}
next_hwnd = Self::next_window(next_hwnd)?;
}
bail!("could not find next window")
}
pub fn window_rect(hwnd: isize) -> eyre::Result<Rect> {
let mut rect = unsafe { std::mem::zeroed() };
if Self::dwm_get_window_attribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &mut rect).is_ok() {
// TODO(raggi): once we declare DPI awareness, we will need to scale the rect.
// let window_scale = unsafe { GetDpiForWindow(hwnd) };
// let system_scale = unsafe { GetDpiForSystem() };
// Ok(Rect::from(rect).scale(system_scale.try_into()?, window_scale.try_into()?))
Ok(Rect::from(rect))
} else {
unsafe { GetWindowRect(HWND(as_ptr!(hwnd)), &mut rect) }.process()?;
Ok(Rect::from(rect))
}
}
/// shadow_rect computes the offset of the shadow position of the window toView on GitHub (pinned to e0709f02bf)
Solutions
- Check that at least one visible, non-minimized window exists on the target monitor before calling
- Enumerate windows with IsWindowVisible filtering yourself to confirm state
- Restart or rescan komorebi's window management state
- Handle the empty-workspace case in your caller instead of treating it as fatal
Example fix
// before
let hwnd = WindowsApi::top_visible_window(start)?;
// after
let hwnd = match WindowsApi::top_visible_window(start) {
Ok(h) => h,
Err(_) => return Ok(()), // empty/hidden workspace is not fatal
}; Defensive patterns
Strategy: try-catch
Validate before calling
// Check at least one visible window exists first
fn has_visible_window() -> bool {
!komorebi_state().windows.iter().any(|w| w.visible) == false
} Try / catch
match WindowsApi::top_visible_window(hwnd) {
Ok(next) => use(next),
Err(e) if e.to_string().contains("could not find next window") => {
log::debug!("no visible window in z-order; treating workspace as empty");
}
Err(e) => return Err(e),
} Prevention
- Treat empty/fully-minimized workspaces as a normal case, not an error
- Keep the starting hwnd fresh; stale hwnds break z-order walks
- Handle window-destroy events before re-enumerating
- Filter minimized/cloaked windows explicitly in your own logic
When it happens
Trigger: Calling WindowsApi::top_visible_window(hwnd) when the starting hwnd is the last in the z-order, all subsequent windows are invisible/minimized, or the hwnd is invalid so the loop immediately fails to find a next window.
Common situations: All windows on a monitor are minimized or hidden; a window was destroyed mid-enumeration; querying a virtual desktop whose windows are all cloaked; empty workspaces in multi-monitor setups.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- failed call to AllowSetForegroundWindow after 5 retries
- window handles for move operation don't match: {} != {}
- could not close window
- could not determine current session id
- could not find device_id for hmonitor: {hmonitor}
AI-assisted analysis of LGUG2Z/komorebi@e0709f02bf (2026-09-06).
Data as JSON: /api/errors/154b9cfd6503cf6d.
Report an issue: GitHub.