Hmbown/CodeWhale · error · anyhow::Error

No API key provided. Pass --api-key or pipe one via stdin.

Error message

No API key provided. Pass --api-key or pipe one via stdin.

What it means

run_login() with no --api-key falls back to read_api_key_from_stdin(), which first checks io::stdin().is_terminal(). If stdin is an interactive terminal it bails immediately with this message rather than hanging on hidden input; piping is the designed non-interactive path.

Source

Thrown at crates/tui/src/lib.rs:7767

/// Apply the same reasoning-preference precedence as interactive `App`
/// construction to non-TUI runtimes.
///
/// `/model` and the config editor persist this preference in `settings.toml`.
/// Exec, review, workflow, ACP, and runtime-thread launches all begin with a
/// `Config`, so copying the saved value here keeps those entry points from
/// silently falling back to a route classifier or an older config.toml value.
fn apply_saved_reasoning_preference(config: &mut Config, settings: &crate::settings::Settings) {
    let Some(reasoning_effort) = settings.reasoning_effort.as_ref() else {
        return;
    };
    config.reasoning_effort = Some(reasoning_effort.clone());
    config.reasoning_effort_inferred_from_legacy_alias = false;
}

fn read_api_key_from_stdin() -> Result<String> {
    let mut stdin = io::stdin();
    if stdin.is_terminal() {
        bail!("No API key provided. Pass --api-key or pipe one via stdin.");
    }
    let mut buffer = String::new();
    stdin.read_to_string(&mut buffer)?;
    let api_key = buffer.trim().to_string();
    if api_key.is_empty() {
        bail!("No API key provided via stdin.");
    }
    Ok(api_key)
}

fn run_login(api_key: Option<String>) -> Result<()> {
    let api_key = match api_key {
        Some(key) => key,
        None => read_api_key_from_stdin()?,
    };
    let saved = config::save_api_key(&api_key)?;
    println!("Saved API key to {}", saved.describe());
    Ok(())

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Pass the key explicitly: `codewhale login --api-key <key>`
  2. Or pipe it: `printf '%s' "$CODEWHALE_API_KEY" | codewhale login`
  3. In scripts, always source the key from a variable or secret store rather than expecting a prompt

Example fix

// before (interactive tty, no key)
$ codewhale login
Error: No API key provided. Pass --api-key or pipe one via stdin.

// after
$ codewhale login --api-key "$CODEWHALE_API_KEY"
// or: $ printf '%s' "$CODEWHALE_API_KEY" | codewhale login
Defensive patterns

Strategy: validation

Validate before calling

: "${CODEWHALE_API_KEY:?set CODEWHALE_API_KEY or pass --api-key}"
codewhale login --api-key "$CODEWHALE_API_KEY"

Prevention

When it happens

Trigger: Running `codewhale login` without --api-key from an interactive shell (stdin is a TTY). Any piped invocation takes the stdin branch instead and never sees this message.

Common situations: Typing `codewhale login` expecting a password-style hidden prompt (there is none); forgetting the flag during a quick local test.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/e38cc9ff84ca4b74. Report an issue: GitHub.