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

  1. Run `codew` or `codewhale` directly inside an interactive terminal emulator such as Terminal.app, iTerm2, or Windows Terminal.
  2. If invoking from a script or scheduler, drop the TUI and use `codewhale exec "…"` for headless, non-TTY prompts.
  3. 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.