wezterm/wezterm · error

TerminalShim::waker called!?

Error message

TerminalShim::waker called!?

What it means

The scrollback-search handler's do_search helper failed at get_pane: the pane whose scrollback should be searched no longer exists, and the server returns ErrorResponse "Error: no such pane {pane_id}". The search itself runs on a spawned promise (sessionhandler.rs:527-533), but the lookup error still flows back through send_response to the client that opened the search.

Source

Thrown at mux/src/ssh.rs:567

                    self.parser
                        .parse(&buf[0..n], |evt| input_queue.push_back(evt), n == buf.len());
                    return Ok(self.input_queue.pop_front());
                } else {
                    let size = *self.size.lock().unwrap();
                    if starting_size != size {
                        return Ok(Some(InputEvent::Resized {
                            cols: size.cols as usize,
                            rows: size.rows as usize,
                        }));
                    }
                }
            }
        }

        fn waker(&self) -> TerminalWaker {
            // TODO: TerminalWaker assumes that we're a SystemTerminal but that
            // isn't the case here.
            panic!("TerminalShim::waker called!?");
        }
    }

    let renderer = termwiz_funcs::new_wezterm_terminfo_renderer();
    let mut shim = TerminalShim {
        stdout: &mut StdoutShim {
            stdout: stdout_write,
            size: Arc::clone(&size),
        },
        size: Arc::clone(&size),
        renderer,
        stdin: &mut stdin_read,
        parser: InputParser::new(),
        input_queue: VecDeque::new(),
    };

    impl<'a> TerminalShim<'a> {
        fn output_line(&mut self, s: &str) -> termwiz::Result<()> {

View on GitHub (pinned to 3ff7522b96)

Solutions

  1. Dismiss the search on pane exit: subscribe to PaneClosed/WindowClosed notifications and close the overlay instead of issuing the RPC
  2. For programmatic search, resolve the pane id from a fresh list immediately before searching
  3. If you need the scrollback of a pane that may die, copy/get the lines while it is alive rather than searching afterwards

Example fix

// before: search with a possibly stale id
let res = conn.search_scrollback(SearchScrollbackRequest { pane_id, pattern, range, limit }).await?;

// after: validate liveness first, degrade gracefully
if !pane_exists(&conn, pane_id).await? {
    anyhow::bail!("pane {pane_id} closed before search");
}
let res = conn.search_scrollback(SearchScrollbackRequest { pane_id, pattern, range, limit }).await?;
Defensive patterns

Strategy: validation

Validate before calling

// Before searching scrollback, confirm the pane is alive
if !pane_exists(&conn, pane_id).await? {
    anyhow::bail!("pane {pane_id} closed; aborting scrollback search");
}
conn.search_scrollback(SearchScrollbackRequest { pane_id, pattern, range, limit }).await?;

Type guard

fn pane_alive(res: &ListPanesResponse, pane_id: PaneId) -> bool {
    fn walk(n: &PaneNode, id: PaneId) -> bool {
        match n {
            PaneNode::Leaf(e) => e.pane_id == id,
            PaneNode::Split { left, right, .. } => walk(left, id) || walk(right, id),
            PaneNode::Empty => false,
        }
    }
    res.tabs.iter().any(|t| walk(t, pane_id))
}

Try / catch

match conn.search_scrollback(SearchScrollbackRequest { pane_id, pattern, range, limit }).await {
    Ok(r) => r,
    Err(e) if e.to_string().contains("no such pane") => {
        // pane died mid-search: close the search UI / return empty results
        SearchScrollbackResponse { results: vec![] }
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: The GUI search overlay (default CTRL+SHIFT+F) being used in a tab whose process exits while the overlay is open (or between keystrokes); a programmatic search_scrollback call with a pane_id from a stale ListPanes snapshot.

Common situations: Searching a tab where a short-lived command already exited; remote/tls domains where the pane was pruned after the client cached its id; scripted capture-and-search racing pane teardown.

Related errors


AI-assisted analysis of wezterm/wezterm@3ff7522b96 (2026-08-20). Data as JSON: /api/errors/61757d1c69bb92d9. Report an issue: GitHub.