wezterm/wezterm · error
invalid window id {}
Error message
invalid window id {} What it means
Thrown by mux::termwizterm::run() after it registers a TermWizTerminalPane and tries to activate it in a caller-supplied window. register_tab() accepts an Option<WindowId>; when you pass Some(id), the code calls mux.get_window_mut(window_id) and that lookup fails because no window with that id exists in the Mux. It means the WindowId is stale or foreign: the window was closed, was purged by the mux, or the id came from a different Mux instance. Passing None instead lets the mux allocate a fresh window and never hits this path.
Source
Thrown at mux/src/termwiztermtab.rs:560
None => {
window_builder = mux.new_empty_window(None, None);
*window_builder
}
};
let pane =
TermWizTerminalPane::new(domain.domain_id(), size, input_tx, render_rx, term_config);
let pane: Arc<dyn Pane> = Arc::new(pane);
let tab = Arc::new(Tab::new(&size));
tab.assign_pane(&pane);
mux.add_tab_and_active_pane(&tab)?;
mux.add_tab_to_window(&tab, window_id)?;
let mut window = mux
.get_window_mut(window_id)
.ok_or_else(|| anyhow::anyhow!("invalid window id {}", window_id))?;
let tab_idx = window.len().saturating_sub(1);
window.save_and_then_set_active(tab_idx);
Ok((pane.pane_id(), window_id))
}
let (pane_id, window_id) = promise::spawn::spawn_into_main_thread(async move {
register_tab(input_tx, render_rx, size, window_id, term_config).await
})
.await?;
let result = promise::spawn::spawn_into_new_thread(move || f(tw_term)).await;
// Since we're typically called with an outstanding Activity token active,
// the dead status of the tab will be ignored until after the activity
// resolves. In the case of SSH where (currently!) several prompts may
// be shown in succession, we don't want to leave lingering dead windows
// on the screen so let's ask the mux to kill off our window now.View on GitHub (pinned to 9c04f79f86)
Solutions
- Pass window_id: None so the mux creates (and owns) a fresh window instead of reusing a possibly-dead id
- Before calling run(), validate the id with mux.get_window(window_id).is_some() and fall back to None if it is gone
- If reusing a returned WindowId, re-validate it immediately before each subsequent call rather than caching it indefinitely
- Treat the error as non-fatal: catch it, retry run() with None
Example fix
// before
let (result, win_id) = run(size, Some(cached_window_id), f, cfg).await;
// after
let mux = Mux::get();
let window_id = if cached_window_id.map(|id| mux.get_window(id).is_some()).unwrap_or(false) {
cached_window_id
} else {
None // let the mux allocate a new window
};
let (result, win_id) = run(size, window_id, f, cfg).await; Defensive patterns
Strategy: validation
Validate before calling
// Before mux::termwizterm::run(size, Some(window_id), f, cfg):
let mux = Mux::get();
let window_id = match window_id {
Some(id) if mux.get_window(id).is_some() => Some(id),
_ => None, // let the mux allocate a fresh window
}; Try / catch
match run(size, window_id, f, cfg).await {
Ok(v) => v,
Err(e) if e.to_string().starts_with("invalid window id") => {
run(size, None, f, cfg).await? // retry in a new window
}
Err(e) => return Err(e),
} Prevention
- Never cache a WindowId across long awaits; re-validate with mux.get_window() before reuse
- Prefer passing window_id: None unless you demonstrably own the target window
- Treat user-closable prompt windows as ephemeral: expect the id to die at any await point
When it happens
Trigger: Calling mux::termwizterm::run(size, Some(window_id), f, config) with a WindowId captured earlier (e.g. from a previous run() return value) after that window has been closed by the user or killed by mux.remove_window; reusing a WindowId across separate wezterm client sessions where the id was allocated in the other process's Mux.
Common situations: Hosting embedded termwiz prompts (SSH authentication/2FA dialogs) in an existing window that may have been dismissed while the async prompt chain was awaited; caching a WindowId across long awaits in Lua/CLI automation; races where the user closes the prompt window before a follow-up prompt is spawned.
Related errors
- window_id {} not found on this server
- window {} has no tabs
- pane {} wasn't in its containing tab!?
- active tab in window {} has no panes
- missing active pane on tab!?
AI-assisted analysis of wezterm/wezterm@9c04f79f86 (2026-08-16).
Data as JSON: /api/errors/b530ed5540965131.
Report an issue: GitHub.