xai-org/grok-build · critical
terminal writer stopped
Error message
terminal writer stopped
What it means
The event loop multiplexes the terminal writer's event channel via tokio::select. When writer_event_rx.recv() returns None, the writer task has terminated (channel closed) while the app is still running, so the loop records a startup error outcome, flushes stall telemetry, and aborts with this anyhow error.
Source
Thrown at crates/codegen/xai-grok-pager/src/app/event_loop.rs:2411
// Leader disconnect: the bridge fires cancel when the IPC channel closes
// Without this arm the loop would hang because AppView holds the client-side tx, keeping acp_rx open
_ = connection_cancel.cancelled() => {
break;
}
// Graceful-quit request from the signal handler
// Kept high in the biased order so a SIGTERM quit isn't starved by an ACP firehose
_ = quit_notify.notified() => {
let effs = dispatch::dispatch(Action::Quit, &mut app);
let _ = process_effects(effs, &mut tasks, &mut app, &progress_tx);
break;
}
writer_event = writer_event_rx.recv() => {
let Some(writer_event) = writer_event else {
app.finish_startup(xai_grok_telemetry::startup::StartupOutcome::Error);
flush_pending_stall(&mut stall_rollup);
return Err(anyhow::anyhow!("terminal writer stopped"));
};
let sequence = match writer_event_sequence(writer_event)
.context("terminal output failed")
{
Ok(sequence) => sequence,
Err(e) => {
app.finish_startup(xai_grok_telemetry::startup::StartupOutcome::Error);
flush_pending_stall(&mut stall_rollup);
return Err(e);
}
};
presenter.acknowledge(sequence);
}
// Biased order: cancellation/quit, writer acks/failures, ACP, task/progress results, updates, input, and render/poll timers
// All of them precede the deliberately-last voice STT arm (see its note below)
// Gated on empty terminal inputView on GitHub (pinned to bc7f02eddd)
Solutions
- Re-run with logging/RUST_BACKTRACE=1 to find why the writer task exited (panic or I/O error) first
- Check that stdout is a valid, writable terminal or pipe and the parent process has not closed it
- Verify terminal size/emulator handles the writer's output (try a plain xterm or TERM=xterm-256color)
- Inspect writer task code for early returns/aborts on non-fatal I/O errors and make them retry or degrade gracefully
Example fix
// before: writer exits on transient write error
writer.send(line).await?;
// after: tolerate transient failures instead of closing the channel
if writer.send(line).await.is_err() {
tracing::warn!("terminal write failed; backing off");
tokio::time::sleep(Duration::from_millis(50)).await;
} Defensive patterns
Strategy: try-catch
Validate before calling
// before launching, ensure stdout is writable
use std::io::Write;
fn stdout_writable() -> bool {
let mut out = std::io::stdout();
out.flush().is_ok()
} Try / catch
match run().await {
Err(e) if e.to_string().contains("terminal writer stopped") => {
eprintln!("TUI writer died; re-run in a persistent terminal: {e:#}");
}
Err(e) => eprintln!("fatal: {e:#}"),
Ok(_) => {}
} Prevention
- Run the TUI attached to a real terminal, not a short-lived pipe
- Enable RUST_BACKTRACE and tracing to capture writer-task panics early
- Avoid killing/closing the parent shell or SSH session while the pager runs
- Monitor writer-task health and restart it instead of letting the channel close
When it happens
Trigger: The terminal writer task exits early — it panics, returns Err on an unwritable/lost stdout (e.g. output pipe closed by the terminal or pager teardown), or is aborted — dropping its sender so recv() yields None in the select branch.
Common situations: Running the TUI with stdout redirected into a pipe that the consumer closes; writer task crash due to an I/O error on a detached/SSH-disconnected terminal; a bug causing writer shutdown before the event loop exits.
Related errors
- Invalid viewport height: {} (terminal height: {})
- cancelled during ignored-only copy
- cancelled after git worktree add
- cancelled after parallel copy
- Connection cancelled
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/d0947360294a3cf9.
Report an issue: GitHub.