{"record":{"id":"ab24a4e792843d42","repo":"Hmbown/CodeWhale","slug":"unavailable-credential","errorCode":null,"errorMessage":"unavailable credential","messagePattern":"unavailable credential","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/credential_handoff.rs","lineNumber":65,"sourceCode":"                .auth_mode\n                .as_deref()\n                .is_some_and(auth_mode_uses_kimi_imported_token);\n        ensure!(!kimi_bearer, \"bearer credentials are not an API key\");\n    }\n    ensure!(source.is_some(), \"no runtime-effective API key\");\n    resolved\n        .api_key\n        .filter(|value| !value.trim().is_empty())\n        .context(\"no usable runtime-effective API key\")\n}\n\npub(crate) fn handoff_secret_line(\n    writer: &mut impl Write,\n    stdout_is_terminal: bool,\n    resolve: impl FnOnce() -> Result<String>,\n) -> Result<()> {\n    prepare_stdout(stdout_is_terminal)?;\n    let secret = Zeroizing::new(resolve().map_err(|_| anyhow::anyhow!(\"unavailable credential\"))?);\n    ensure!(!secret.trim().is_empty(), \"credential handoff was empty\");\n    let written = writeln!(writer, \"{}\", secret.as_str());\n    if written.is_ok() || written.is_err_and(|error| error.kind() == ErrorKind::BrokenPipe) {\n        return Ok(());\n    }\n    bail!(\"credential handoff could not write to stdout\")\n}\n#[cfg(test)]\nmod tests;\n","sourceCodeStart":47,"sourceCodeEnd":75,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/cli/src/credential_handoff.rs#L47-L75","documentation":"`codewhale auth print-api-key` writes the runtime-effective API key to a piped stdout for a local client. Any resolution failure is deliberately flattened to \"unavailable credential\" so the credential channel carries no diagnostics an unintended reader could exploit. Real causes include: resolved provider differs from requested, OAuth bearer credentials where an API key is required (codex/xai/moonshot token modes), no runtime-effective key at all, or a whitespace-only key.","triggerScenarios":"Piping `codewhale auth print-api-key` when the account uses OAuth bearer auth instead of an API key, when --provider does not match the configured provider, or when no key is configured anywhere (config, secret store, env).","commonSituations":"Wrapper scripts assuming a plain API key exists after cloud login; xAI/Codex/Moonshot accounts authenticated with OAuth tokens; provider override flags mismatching the stored configuration.","solutions":["Run the same command's diagnostics outside a pipe (`codewhale doctor`, or any non-handoff command) to see the real reason","If the account uses OAuth bearer credentials, configure a plain API key instead (--api-key or provider key login)","Ensure the requested provider matches the configured one","Scripts should detect this exact message on stderr and fall back to prompting, not retry"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"key=$(codewhale auth print-api-key --provider openai 2>err.txt)\nif [ -z \"$key\" ]; then\n  if grep -q \"unavailable credential\" err.txt; then\n    # resolution failed and the reason is redacted from the pipe — diagnose unpiped:\n    codewhale doctor\n    exit 1\n  fi\nfi","preventionTips":["Never parse the handoff pipe for diagnostics — the message is deliberately opaque","Run `codewhale doctor` (or any non-handoff command) first to confirm an API-key credential exists","Know your auth mode: OAuth bearer accounts (codex/xai token/moonshot imported) can never satisfy print-api-key","Check provider spelling on --provider before scripting the handoff"],"tags":["cli","auth","credentials","redaction","pipe","rust"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}