Hmbown/CodeWhale · error · io::Error
terminal input pump did not pause before child terminal…
Error message
terminal input pump did not pause before child terminal handoff
What it means
pause_terminal_input_for_child_terminal sets a `paused` flag and waits (bounded by TERMINAL_INPUT_CHILD_PAUSE_TIMEOUT) for the input-pump thread to acknowledge via `paused_ack`. If the ack never arrives before the deadline, it rolls both flags back and returns ErrorKind::TimedOut, refusing the child-terminal handoff so the pump is never left in a half-paused state.
Solutions
- Verify the terminal input pump thread is alive and processing gates before handing off to a child terminal.
- Increase TERMINAL_INPUT_CHILD_PAUSE_TIMEOUT if the platform legitimately needs longer to ack.
- Retry the handoff after confirming pump health.
Defensive patterns
Strategy: fallback
Validate before calling
// before handoff
if !terminal_pump_is_alive() { restart_pump()?; } Try / catch
match pause_terminal_input_for_child_terminal(&gate) {
Err(e) if e.kind() == io::ErrorKind::TimedOut => abort_handoff_gracefully(),
Ok(guard) => run_child_terminal(guard),
Err(e) => return Err(e),
} Prevention
- Keep the pump poll loop responsive (no long blocking work).
- Health-check the pump thread before handoff.
- Size TERMINAL_INPUT_CHILD_PAUSE_TIMEOUT to the slowest supported platform.
When it happens
Trigger: Calling pause_terminal_input_for_child_terminal when the pump thread is stuck, busy, or dead and does not observe `paused` within the timeout (tested by the refusal test).
Common situations: Pump thread blocked on a read that never yields, thread already exited, extreme system load delaying the poll loop past the deadline.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- child wall-time budget exhausted
- for
- LSP diagnostics timed out waiting for another document
- Task store is busy; state is unavailable
- terminal input pump did not pause before launching editor
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/fc3b42d3f06aca47.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/ui/terminal_input.rs:122
/// not run the child, because that is exactly the keystroke-splitting state
/// this guards against. A process with no pump published (tests, non-TUI
/// callers) has nothing to pause and succeeds with an inert guard, matching
/// [`TerminalInputPump::pause_for_child_terminal`]'s `handle.is_none()` case.
pub(crate) fn pause_terminal_input_for_child() -> io::Result<ChildTerminalInputPause> {
let Some(gate) = CHILD_TERMINAL_GATE
.lock()
.ok()
.and_then(|gate| gate.clone())
else {
return Ok(ChildTerminalInputPause { gate: None });
};
gate.paused.store(true, Ordering::Release);
let deadline = Instant::now() + TERMINAL_INPUT_CHILD_PAUSE_TIMEOUT;
while !gate.paused_ack.load(Ordering::Acquire) {
if Instant::now() >= deadline {
gate.paused_ack.store(false, Ordering::Release);
gate.paused.store(false, Ordering::Release);
return Err(io::Error::new(
io::ErrorKind::TimedOut,
"terminal input pump did not pause before child terminal handoff",
));
}
// Blocking-call convention (#6149): a bounded retry, capped by
// `TERMINAL_INPUT_CHILD_PAUSE_TIMEOUT`, in a synchronous API whose
// caller is about to block this very thread on a foreground editor
// for as long as the user keeps it open. `tokio::time` is not
// reachable from here and would not change what the thread does.
thread::sleep(TERMINAL_INPUT_CHILD_PAUSE_POLL_INTERVAL);
}
Ok(ChildTerminalInputPause { gate: Some(gate) })
}
impl Drop for ChildTerminalInputPause {
fn drop(&mut self) {
if let Some(gate) = self.gate.take() {
gate.paused_ack.store(false, Ordering::Release);View on GitHub (pinned to 73e0f67d83)