{"record":{"id":"ac6b88329514a404","repo":"Hmbown/CodeWhale","slug":"api-key-input-is-unexpectedly-large","errorCode":null,"errorMessage":"API key input is unexpectedly large","messagePattern":"API key input is unexpectedly large","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/cloud.rs","lineNumber":964,"sourceCode":"        return None;\n    }\n    std::env::var(variable)\n        .ok()\n        .filter(|value| !value.trim().is_empty())\n}\n\nfn read_key_from_stdin() -> Result<String> {\n    let mut bytes = Vec::new();\n    io::stdin()\n        .take(MAX_API_KEY_STDIN_BYTES + 1)\n        .read_to_end(&mut bytes)\n        .context(\"failed to read API key from stdin\")?;\n    parse_key_input(bytes)\n}\n\nfn parse_key_input(bytes: Vec<u8>) -> Result<String> {\n    if bytes.len() as u64 > MAX_API_KEY_STDIN_BYTES {\n        bail!(\"API key input is unexpectedly large\");\n    }\n    let value = String::from_utf8(bytes).context(\"API key from stdin is not valid UTF-8\")?;\n    let value = value.trim().to_string();\n    validate_api_key(&value)?;\n    Ok(value)\n}\n\nfn read_key_hidden(provider: &str) -> Result<String> {\n    if !io::stdin().is_terminal() {\n        bail!(\"interactive key entry requires a terminal; use `--api-key-stdin` for piped input\");\n    }\n    let term = console::Term::stderr();\n    term.write_str(&format!(\"Enter {provider} API key: \"))\n        .context(\"failed to write API key prompt\")?;\n    let value = term\n        .read_secure_line()\n        .context(\"failed to read API key securely\")?;\n    term.write_line(\"\").ok();","sourceCodeStart":946,"sourceCodeEnd":982,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/cli/src/cloud.rs#L946-L982","documentation":"When reading an API key from stdin, the CLI reads at most MAX_API_KEY_STDIN_BYTES = 5120 bytes (4096 max key + 1024 slack) and rejects anything larger before parsing. This bail fires when the piped input exceeds that cap, protecting against accidentally piping files or unbounded streams into the key prompt.","triggerScenarios":"`cat large-file.json | codewhale ... --api-key-stdin` where the file is >5 KiB; piping a full docker-credentials JSON, PEM bundle, or config file instead of the bare key; a stuck pipe that keeps producing output.","commonSituations":"Automation scripts reusing a generic `cat $CREDS | ...` pattern for all secret inputs; accidentally piping the wrong file; keys embedded in larger response bodies that were never extracted.","solutions":["Pipe only the raw key: printf '%s' \"$KEY\" | codewhale ... --api-key-stdin","Extract the key field first: jq -r .api_key creds.json | codewhale ... --api-key-stdin","Verify the source file: wc -c key.txt must be <= 5120 (and the trimmed key <= 4096)","If you genuinely have a huge token, it is not a supported API key - issue a standard-length key"],"exampleFix":"# before\ncat ./service-account-credentials.json | codewhale cloud login --api-key-stdin\n# after\njq -r .api_key ./service-account-credentials.json | tr -d '\\n' | codewhale cloud login --api-key-stdin","handlingStrategy":"validation","validationCode":"const MAX_API_KEY_STDIN_BYTES: u64 = 5120; // 4096 key + 1024 slack\n\nfn stdin_size_ok() -> std::io::Result<bool> {\n    use std::io::{Seek, SeekFrom};\n    let mut f = std::io::stdin().lock();\n    if f.seek(SeekFrom::End(0))? <= MAX_API_KEY_STDIN_BYTES as i64 {\n        f.seek(SeekFrom::Start(0))?;\n        Ok(true)\n    } else {\n        Ok(false)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never cat whole credential files into --api-key-stdin; extract the token field first","wc -c the key source and assert <= 5120 before piping","Treat oversized input as a wrong-file signal, not a key"],"tags":["cloud","api-key","stdin","input-limits"],"backgroundTag":"input-too-large","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}