Hmbown/CodeWhale · error · anyhow::Error
Codewhale TUI requires an interactive terminal (stdin and st
Error message
Codewhale TUI requires an interactive terminal (stdin and stdout must be a TTY). Open a real terminal (Terminal.app, iTerm, Windows Terminal, …) and run `codew` or `codewhale` there — not from a pipe, cron job, or non-TTY launcher. For headless prompts use `codewhale exec "…"` instead.
What it means
Error "Codewhale TUI requires an interactive terminal (stdin and stdout must be a TTY). Open a real terminal (Terminal.app, iTerm, Windows Terminal, …) and run `codew` or `codewhale` there — not from a pipe, cron job, or non-TTY launcher. For headless prompts use `codewhale exec "…"` instead." thrown in Hmbown/CodeWhale.
Source
Thrown at crates/tui/src/tui/ui/terminal.rs:57
pub(crate) fn collect_pending_terminal_events(
input: &TerminalInputPump,
pending: &mut VecDeque<Event>,
) -> io::Result<()> {
while let Some(event) = input.try_recv()? {
pending.push_back(event);
}
Ok(())
}
/// Refuse to enter raw mode unless both interactive streams are TTYs.
///
/// Keeping this check independent from `std::io` makes the launch contract
/// testable without trying to manipulate the test runner's own terminal.
pub(crate) fn require_interactive_terminal(stdin_is_tty: bool, stdout_is_tty: bool) -> Result<()> {
if stdin_is_tty && stdout_is_tty {
return Ok(());
}
Err(anyhow::anyhow!(
"Codewhale TUI requires an interactive terminal (stdin and stdout must be a TTY).\n\
Open a real terminal (Terminal.app, iTerm, Windows Terminal, …) and run `codew` \
or `codewhale` there — not from a pipe, cron job, or non-TTY launcher.\n\
For headless prompts use `codewhale exec \"…\"` instead."
))
}
/// One side of the raw-mode probe abandonment handshake between the startup
/// probe timeout and the blocking `enable_raw_mode` task finishing late.
///
/// Each side publishes its own flag (`publish`), then checks whether the
/// other side's flag (`check`) is already up; a `true` return means this
/// side must disable raw mode again. `SeqCst` ordering guarantees that when
/// both sides run, at least one observes the other's flag, so a raw-mode
/// enable landing after the probe timeout is always undone. Both sides
/// observing each other is fine — a duplicate `disable_raw_mode` is a no-op.
pub(crate) fn raw_mode_probe_handshake(publish: &AtomicBool, check: &AtomicBool) -> bool {
publish.store(true, Ordering::SeqCst);View on GitHub (pinned to 0c42157ee5)
Solutions
- Run `codew` or `codewhale` directly inside an interactive terminal emulator such as Terminal.app, iTerm2, or Windows Terminal.
- If invoking from a script or scheduler, drop the TUI and use `codewhale exec "…"` for headless, non-TTY prompts.
- Check that stdin and stdout are not redirected through pipes or files; relaunch with both attached to a real TTY.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/tui/src/tui/ui/terminal.rs:57 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/71ce44201494de58.
Report an issue: GitHub.