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

  1. Retry the suspend (the pause flag is rolled back, so state is consistent)
  2. Check that the input reader loop responds promptly to the pause flag and calls reader_parked
  3. Reduce input event backlog before suspending
  4. 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

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


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/80d61e9fd92b7ab1. Report an issue: GitHub.