Hmbown/CodeWhale · error · anyhow::Error

API key contains invalid control characters

Error message

API key contains invalid control characters

What it means

After the length check, the CLI rejects any API key containing ASCII control characters (code points <= 0x1f or 0x7f DEL). This bail fires when the key value embeds newlines, carriage returns, tabs, NULs, or escape bytes - usually the residue of how the value was stored or transported rather than the key itself.

Source

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

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 0c42157ee5)

Solutions

  1. Strip interior control bytes before storing: tr -d '\r\n\000' < key.txt
  2. Fix the env var or config entry to contain the single-line key with no escapes
  3. Re-paste the key manually in the hidden prompt to eliminate paste artifacts
  4. If a secrets manager wraps keys, extract the raw token field instead of the wrapper

Example fix

# before
printf 'sk-abc\nsk-def' | codewhale cloud login --api-key-stdin   # interior newline
# after
printf '%s' "$(tr -d '\r\n' < key.txt)" | codewhale cloud login --api-key-stdin
Defensive patterns

Strategy: validation

Validate before calling

fn has_no_control_chars(s: &str) -> bool {
    !s.chars().any(|c| c <= '\u{001f}' || c == '\u{007f}')
}

Type guard

fn is_sanitized_api_key(key: &str) -> bool {
    (8..=4096).contains(&key.trim().len())
        && !key.trim().chars().any(|c| c <= '\u{001f}' || c == '\u{007f}')
}

Prevention

When it happens

Trigger: A key passed via --api-key-stdin or a prompt containing an embedded \n or \r; an env var set with a literal escape sequence; a config file value with a stray tab; binary garbage pasted into the prompt.

Common situations: Windows CRLF line endings when piping key files; secrets managers that store multi-line values; shell quoting that preserves \n escape sequences instead of newlines being trimmed (leading/trailing are trimmed, interior ones are not); terminal paste glitches.

Related errors


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