Hmbown/CodeWhale · error

API key contains invalid control characters

Error message

API key contains invalid control characters

What it means

validate_api_key rejects any key string containing ASCII control characters (<= 0x1f or 0x7f). Control characters in an API key indicate a mangled paste, embedded newline, or binary corruption, so the CLI refuses the value rather than sending a guaranteed-invalid credential to the server.

Solutions

  1. Re-copy the key from the source UI in one clean selection and pass it again
  2. If reading from a file, strip whitespace: use `--api-key-stdin` (it trims) or `tr -d '\n\r' < keyfile`
  3. Check the value with `echo -n "$KEY" | od -c | head` to find hidden control bytes
  4. Avoid multiline shell variables; use a single-line quoted assignment

Example fix

// before
KEY=$(cat key.txt)                 # includes trailing \n
// after
KEY=$(tr -d '\n\r' < key.txt)      # or use --api-key-stdin, which trims
Defensive patterns

Strategy: validation

Validate before calling

fn has_control_chars(s: &str) -> bool {
    s.chars().any(|c| c <= '\u{001f}' || c == '\u{007f}')
}
// strip before use: let clean: String = raw.trim().chars().filter(|c| !has_control_chars(&c.to_string())).collect();

Type guard

fn is_clean_key(s: &str) -> bool {
    !s.is_empty() && !s.chars().any(|c| c.is_ascii_control())
}

Prevention

When it happens

Trigger: Calling any path that runs validate_api_key (crates/cli/src/cloud.rs:1138) with a key containing characters like \n, \r, \t, or 0x7f — commonly a key copied with a trailing newline or read from a file without trimming.

Common situations: Pasting a key from a terminal where a newline was captured, reading the key from a file with a trailing newline, terminal emulators inserting escape sequences during copy, or shell variable assignment with embedded newlines.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/b09ef7775a9cc793. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/cloud.rs:1138

fn validate_device_code(code: &str) -> Result<()> {
    if code.len() != 43
        || !code
            .bytes()
            .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_'))
    {
        bail!("The Codewhale service returned an invalid device authorization response");
    }
    Ok(())
}

fn validate_api_key(key: &str) -> Result<()> {
    let bytes = key.len();
    if bytes < MIN_API_KEY_BYTES || bytes as u64 > MAX_API_KEY_BYTES {
        bail!("API key must be {MIN_API_KEY_BYTES}-{MAX_API_KEY_BYTES} UTF-8 bytes");
    }
    if key.chars().any(is_ascii_control) {
        bail!("API key contains invalid control characters");
    }
    Ok(())
}

fn validate_label(label: &str) -> Result<String> {
    let label = label.split_whitespace().collect::<Vec<_>>().join(" ");
    if label.is_empty()
        || label.chars().count() > MAX_KEY_LABEL_CHARS
        || label.chars().any(is_ascii_control)
    {
        bail!("key label must contain 1-{MAX_KEY_LABEL_CHARS} characters");
    }
    Ok(label)
}

fn is_ascii_control(character: char) -> bool {
    character <= '\u{001f}' || character == '\u{007f}'
}

View on GitHub (pinned to 73e0f67d83)