LGUG2Z/komorebi · warning
window handles for move operation don't match: {} != {}
Error message
window handles for move operation don't match: {} != {} What it means
In process_event, when handling a pending EVENT_SYSTEM_MOVESIZE END, komorebi compares the stored pending move's window handle with the hwnd of the window in the current move event. If they differ, the pending move is stale or belongs to another window, so it aborts with this error naming both handles.
Source
Thrown at komorebi/src/process_event.rs:672
WindowsApi::bring_window_to_top(window.hwnd)?;
let pending_move_op = Arc::make_mut(&mut self.pending_move_op);
*pending_move_op = Option::from((monitor_idx, workspace_idx, window.hwnd));
}
WindowManagerEvent::MoveResizeEnd(_, window) => {
// We need this because if the event ends on a different monitor,
// that monitor will already have been focused and updated in the state
let pending = *self.pending_move_op;
// Always consume the pending move op whenever this event is handled
let pending_move_op = Arc::make_mut(&mut self.pending_move_op);
*pending_move_op = None;
// If the window handles don't match then something went wrong and the pending move
// is not related to this current move, if so abort this operation.
if let Some((_, _, w_hwnd)) = pending
&& w_hwnd != window.hwnd
{
color_eyre::eyre::bail!(
"window handles for move operation don't match: {} != {}",
w_hwnd,
window.hwnd
);
}
let target_monitor_idx = self
.monitor_idx_from_current_pos()
.ok_or_eyre("cannot get monitor idx from current position")?;
let focused_monitor_idx = self.focused_monitor_idx();
let focused_workspace_idx = self.focused_workspace_idx().unwrap_or_default();
let window_management_behaviour =
self.window_management_behaviour(focused_monitor_idx, focused_workspace_idx);
let workspace = self.focused_workspace_mut()?;
let focused_container_idx = workspace.focused_container_idx();
let new_position = WindowsApi::window_rect(window.hwnd)?;View on GitHub (pinned to e0709f02bf)
Solutions
- Update komorebi; this is an internal invariant check and recent versions may reconcile stale pending moves instead of failing.
- Reproduce slowly / disable conflicting drag utilities (PowerToys FancyZones, DisplayFusion) that inject move events.
- If persistent, report with the two hwnd values from the message and steps to reproduce.
Defensive patterns
Strategy: retry
Validate before calling
// Caller-side guard: ensure the event's hwnd still matches the pending move before replaying
if pending.hwnd != event.hwnd { return Ok(()); /* drop stale event instead of failing */ } Try / catch
if let Err(e) = process_event(&event) {
if e.to_string().contains("window handles for move operation don't match") {
tracing::debug!("stale pending move ignored: {e}");
}
} Prevention
- Avoid dragging windows extremely rapidly
- Disable third-party window managers/overlays that inject move events (FancyZones, DisplayFusion)
- Update komorebi — stale pending-move handling improves across versions
When it happens
Trigger: A WinEvent hook move/resize end event arrives whose hwnd does not match the recorded pending move hwnd — e.g. rapid drag of another window before the previous pending move was cleared, out-of-order events, or a destroyed-and-recreated window reusing state.
Common situations: Dragging windows very quickly, minimizing/closing a window mid-drag, race with floating window management, multi-monitor drags generating interleaved events.
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
- failed call to AllowSetForegroundWindow after 5 retries
- could not close window
- could not find next 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/dbc4df23bcdbe779.
Report an issue: GitHub.