{"record":{"id":"b530ed5540965131","repo":"wezterm/wezterm","slug":"invalid-window-id","errorCode":null,"errorMessage":"invalid window id {}","messagePattern":"invalid window id (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mux/src/termwiztermtab.rs","lineNumber":560,"sourceCode":"            None => {\n                window_builder = mux.new_empty_window(None, None);\n                *window_builder\n            }\n        };\n\n        let pane =\n            TermWizTerminalPane::new(domain.domain_id(), size, input_tx, render_rx, term_config);\n        let pane: Arc<dyn Pane> = Arc::new(pane);\n\n        let tab = Arc::new(Tab::new(&size));\n        tab.assign_pane(&pane);\n\n        mux.add_tab_and_active_pane(&tab)?;\n        mux.add_tab_to_window(&tab, window_id)?;\n\n        let mut window = mux\n            .get_window_mut(window_id)\n            .ok_or_else(|| anyhow::anyhow!(\"invalid window id {}\", window_id))?;\n        let tab_idx = window.len().saturating_sub(1);\n        window.save_and_then_set_active(tab_idx);\n\n        Ok((pane.pane_id(), window_id))\n    }\n\n    let (pane_id, window_id) = promise::spawn::spawn_into_main_thread(async move {\n        register_tab(input_tx, render_rx, size, window_id, term_config).await\n    })\n    .await?;\n\n    let result = promise::spawn::spawn_into_new_thread(move || f(tw_term)).await;\n\n    // Since we're typically called with an outstanding Activity token active,\n    // the dead status of the tab will be ignored until after the activity\n    // resolves.  In the case of SSH where (currently!) several prompts may\n    // be shown in succession, we don't want to leave lingering dead windows\n    // on the screen so let's ask the mux to kill off our window now.","sourceCodeStart":542,"sourceCodeEnd":578,"githubUrl":"https://github.com/wezterm/wezterm/blob/9c04f79f86649f76a8c978ff4b674f60297a6ec9/mux/src/termwiztermtab.rs#L542-L578","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlet (result, win_id) = run(size, Some(cached_window_id), f, cfg).await;\n\n// after\nlet mux = Mux::get();\nlet window_id = if cached_window_id.map(|id| mux.get_window(id).is_some()).unwrap_or(false) {\n    cached_window_id\n} else {\n    None // let the mux allocate a new window\n};\nlet (result, win_id) = run(size, window_id, f, cfg).await;","handlingStrategy":"validation","validationCode":"// Before mux::termwizterm::run(size, Some(window_id), f, cfg):\nlet mux = Mux::get();\nlet window_id = match window_id {\n    Some(id) if mux.get_window(id).is_some() => Some(id),\n    _ => None, // let the mux allocate a fresh window\n};","typeGuard":null,"tryCatchPattern":"match run(size, window_id, f, cfg).await {\n    Ok(v) => v,\n    Err(e) if e.to_string().starts_with(\"invalid window id\") => {\n        run(size, None, f, cfg).await? // retry in a new window\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["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"],"tags":["rust","wezterm","mux","termwiz","window-id"],"backgroundTag":"invalid-resource-id","analyzedSha":"9c04f79f86649f76a8c978ff4b674f60297a6ec9","analyzedAt":"2026-08-16T21:23:27.157Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}