xai-org/grok-build · error
terminal input reader did not park before suspend
Error message
terminal input reader did not park before suspend
What it means
An io::Error of kind TimedOut returned by suspend_for_child when park_input_reader fails to get the terminal input reader to acknowledge the pause within 500ms. The suspend sequence requires the reader parked before handing the terminal to a child process; if it doesn't park, the handoff is aborted and the pause flag is rolled back.
Source
Thrown at crates/codegen/xai-grok-pager/src/app/event_loop.rs:371
reader_parked.load(Ordering::Acquire)
}
/// Suspend the TUI, let a blocking child own the tty, then restore it.
///
/// Input is parked before the asynchronous frame writer is drained with a bounded wait, so neither the reader nor a queued frame can race the child.
/// A park or drain timeout returns without starting the child; the caller keeps the request pending and retries it later.
fn suspend_for_child(
screen_mode: crate::app::ScreenMode,
terminal: &mut PagerTerminal,
input_paused: &std::sync::atomic::AtomicBool,
reader_parked: &std::sync::atomic::AtomicBool,
input_rx: &mut tokio::sync::mpsc::UnboundedReceiver<TimedInputEvent>,
run_child: impl FnOnce(),
) -> std::io::Result<Option<(u16, u16)>> {
use std::sync::atomic::Ordering;
if !park_input_reader(input_paused, reader_parked, Duration::from_millis(500)) {
input_paused.store(false, Ordering::Release);
return Err(std::io::Error::new(
std::io::ErrorKind::TimedOut,
"terminal input reader did not park before suspend",
));
}
let writer_sync = terminal.backend_mut().writer_mut().writer_sync().clone();
match writer_sync.wait_drained(Duration::from_millis(750)) {
Ok(crate::render::draw::WriterDrain::Drained) => {}
Ok(crate::render::draw::WriterDrain::TimedOut) => {
input_paused.store(false, Ordering::Release);
return Err(std::io::Error::new(
std::io::ErrorKind::TimedOut,
"terminal writer did not drain before suspend",
));
}
Err(error) => {
input_paused.store(false, Ordering::Release);
return Err(error);
}View on GitHub (pinned to bc7f02eddd)
Solutions
- Retry the suspend (the pause flag is rolled back, so state is consistent)
- Check that the input reader loop responds promptly to the pause flag and calls reader_parked
- Reduce input event backlog before suspending
- Increase the 500ms park window if the environment is legitimately slow
Defensive patterns
Strategy: retry
Try / catch
if let Err(e) = suspend_for_child(...) {
if e.kind() == std::io::ErrorKind::TimedOut { retry_suspend_once(); }
} Prevention
- Drain queued input events before requesting suspend
- Keep the input reader loop responsive to the pause flag
- Avoid suspend under heavy input replay/paste storms
When it happens
Trigger: Input reader thread/event loop not reaching its park state within 500 ms — e.g. a flood of queued input events, a blocked input_rx consumer, or scheduler starvation under heavy load.
Common situations: User typing/pasting rapidly while an editor or child process is about to launch; slow CI/SSH terminals delaying event loop wakeup; regression in the input reader loop.
Related errors
- terminal writer did not drain before suspend
- wait failed: {body}
- unknown key notation: <{notation}>
- WebSocket connection timed out after {} seconds
- GCS download stalled: no data received for {chunk_timeout:?}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/80d61e9fd92b7ab1.
Report an issue: GitHub.