Hmbown/CodeWhale · error
terminal host window owner changed
Error message
terminal host window owner changed
What it means
WindowControl::hwnd validates that the cached window handle still belongs to the same owning process recorded at capture time. GetWindowThreadProcessId returning a different (or zero) pid means the original host window was destroyed and possibly replaced, so the cached handle is invalid and this error is raised.
Solutions
- Re-run capture to bind to the new host window and update the cached handle/owner pid, then retry the operation.
- Check that the terminal that started the TUI is still the active window; restart the TUI in the new terminal if not.
- Guard toggle flows so they re-validate the host (capture) if hwnd reports an owner change.
Defensive patterns
Strategy: try-catch
Try / catch
match host.hwnd() {
Err(e) if e.to_string().contains("owner changed") => { state.host = Some(WindowControl::capture()?); retry(); }
other => other?,
} Prevention
- Validate owner pid before every use of a cached HWND (as hwnd() does).
- Re-capture after any terminal restart or long idle period.
- Don't cache window handles across operations that can outlive the host process.
- Fail soft: degrade to non-pinned mode when the host is gone.
When it happens
Trigger: Calling hwnd (e.g. from observe during toggle_pin or wait_for) when the current owner pid of the cached HWND differs from self.owner_pid — the terminal host process restarted or the window was destroyed.
Common situations: Windows Terminal/conhost restarted while the TUI ran; the user closed and reopened the terminal; a shell integration reset the console window between capture and a later toggle.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- terminal host window no longer exists
- terminal maximize request was rejected
- terminal restore request was rejected
- terminal restore was not observed before the deadline
- terminal window change was not observed before the deadline
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/9653e7d219bb5f15.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/window_control.rs:122
GetWindowThreadProcessId(hwnd, Some(&mut owner_pid));
}
if owner_pid == 0 {
bail!("terminal host window no longer exists");
}
Ok(Self {
handle: hwnd.0 as isize,
owner_pid,
})
}
fn hwnd(self) -> Result<HWND> {
let hwnd = HWND(self.handle as *mut _);
let mut owner_pid = 0;
unsafe {
GetWindowThreadProcessId(hwnd, Some(&mut owner_pid));
}
if owner_pid != self.owner_pid {
bail!("terminal host window owner changed");
}
Ok(hwnd)
}
}
#[derive(Clone, Copy)]
struct Observation {
rect: RECT,
topmost: bool,
maximized: bool,
}
impl Observation {
fn matches(self, target: Self) -> bool {
self.topmost == target.topmost
&& self.maximized == target.maximized
&& (target.maximized || self.rect == target.rect)
}View on GitHub (pinned to 73e0f67d83)