LGUG2Z/komorebi · error

could not close window

Error message

could not close window

What it means

komorebi's close_window sends a WM_CLOSE message to the target window via the Win32 PostMessageW API. If PostMessageW returns an error (e.g. invalid handle or message refused), komorebi bails with 'could not close window'. It means the OS refused the request to close that window.

Source

Thrown at komorebi/src/windows_api.rs:672

            };
        } else {
            unsafe {
                let _ = ShowWindow(HWND(as_ptr!(hwnd)), command);
            };
        }
    }

    pub fn minimize_window(hwnd: isize) {
        Self::show_window(hwnd, SW_MINIMIZE);
    }

    fn post_message(hwnd: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> eyre::Result<()> {
        unsafe { PostMessageW(Option::from(hwnd), message, wparam, lparam) }.process()
    }

    pub fn close_window(hwnd: isize) -> eyre::Result<()> {
        if Self::post_message(HWND(as_ptr!(hwnd)), WM_CLOSE, WPARAM(0), LPARAM(0)).is_err() {
            bail!("could not close window");
        }

        Ok(())
    }

    pub fn hide_window(hwnd: isize) {
        Self::show_window(hwnd, SW_HIDE);
    }

    pub fn restore_window(hwnd: isize) {
        Self::show_window(hwnd, SW_SHOWNOACTIVATE);
    }

    pub fn unmaximize_window(hwnd: isize) {
        Self::show_window(hwnd, SW_NORMAL);
    }

    pub fn maximize_window(hwnd: isize) {

View on GitHub (pinned to e0709f02bf)

Solutions

  1. Verify the hwnd is still valid before closing (IsWindow) and refresh komorebi's window list
  2. Run komorebi with the same or higher privilege level as the target application
  3. Check that the window isn't a protected system/elevated process window; use taskkill or close it manually
  4. Restart komorebi to resynchronize hwnd state

Example fix

// before
WindowsApi::close_window(stale_hwnd)?;
// after
if WindowsApi::is_window(stale_hwnd) {
    WindowsApi::close_window(stale_hwnd)?;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust (windows crate)
use windows::Win32::UI::WindowsAndMessaging::IsWindow;
fn can_close(hwnd: isize) -> bool {
    unsafe { IsWindow(Some(HWND(hwnd as _))).as_bool() }
}

Type guard

fn window_is_valid(hwnd: isize) -> bool {
    hwnd != 0 && unsafe { IsWindow(Some(HWND(hwnd as _))).as_bool() }
}

Try / catch

match WindowsApi::close_window(hwnd) {
    Ok(()) => {},
    Err(e) if e.to_string().contains("could not close window") => {
        log::warn!("window {hwnd} refused WM_CLOSE or is gone; refreshing window list");
        refresh_window_state();
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling WindowsApi::close_window(hwnd) with an hwnd that is stale/invalid, belongs to another desktop or elevated process, or when PostMessageW fails for a protected/system window.

Common situations: A window was closed or recreated between layout passes so komorebi holds a dead hwnd; attempting to close elevated (admin) application windows from a non-elevated komorebi; UWP/system windows that ignore WM_CLOSE.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of LGUG2Z/komorebi@e0709f02bf (2026-09-06). Data as JSON: /api/errors/9a5ff6fb4d8ed5bc. Report an issue: GitHub.