Hmbown/CodeWhale · error · anyhow::Error
no usable runtime-effective API key
Error message
no usable runtime-effective API key
What it means
After confirming a credential source exists, `resolve_api_key` unwraps `resolved.api_key`, filtering out whitespace-only/empty values, and attaches this context if it is None or blank. So a source was recorded but the actual key string is missing or empty — an inconsistency between credential metadata and the stored value.
Solutions
- Re-enter the API key via the provider's key setup command so the stored value is non-empty.
- Delete the stale/empty credential entry and set it fresh.
- Check for an empty env-var override (e.g. `PROVIDER_API_KEY=""`) and unset it.
- Inspect the secret store/config for the provider slot and confirm the stored value length.
Example fix
// before export OPENROUTER_API_KEY="" # source exists, value empty codewhale handoff openrouter // after unset OPENROUTER_API_KEY codewhale auth set openrouter sk-or-...
Defensive patterns
Strategy: validation
Validate before calling
// Re-set the key if the stored value is blank
if stored_key.trim().is_empty() { codewhale auth set <provider> <new-key>; } Prevention
- Never save empty/placeholder keys during setup; validate non-empty before storing
- Audit config templates so ${KEY} placeholders get substituted
- Unset (don't empty) env-var overrides that should not apply
When it happens
Trigger: The secret store entry or config key exists but holds an empty/whitespace string; a key was deleted or truncated but its source marker remains; an override set the key to `""`.
Common situations: Partially completed setup where the user saved an empty key; secret-store corruption or a failed write; templated config where the key placeholder wasn't substituted; env var set to empty string.
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
- api_key cannot be empty string
- bearer credentials are not an API key
- Codewhale-owned OAuth credentials at
- Codex client
- Failed to list models: HTTP
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/5998aef482cfca0f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/credential_handoff.rs:55
let source = resolved.api_key_source;
if source != Some(RuntimeApiKeySource::Cli) {
if provider == ProviderKind::OpenaiCodex {
bail!("bearer credentials are not an API key");
}
let uses_api_key = provider != ProviderKind::Xai
|| xai_auth_diagnostics(store, runtime_overrides).evaluates_runtime_api_key();
ensure!(uses_api_key, "OAuth bearer credentials are not an API key");
let kimi_bearer = provider == ProviderKind::Moonshot
&& resolved
.auth_mode
.as_deref()
.is_some_and(auth_mode_uses_kimi_imported_token);
ensure!(!kimi_bearer, "bearer credentials are not an API key");
}
ensure!(source.is_some(), "no runtime-effective API key");
resolved
.api_key
.filter(|value| !value.trim().is_empty())
.context("no usable runtime-effective API key")
}
pub(crate) fn handoff_secret_line(
writer: &mut impl Write,
stdout_is_terminal: bool,
resolve: impl FnOnce() -> Result<String>,
) -> Result<()> {
prepare_stdout(stdout_is_terminal)?;
let secret = Zeroizing::new(resolve().map_err(|_| anyhow::anyhow!("unavailable credential"))?);
ensure!(!secret.trim().is_empty(), "credential handoff was empty");
let written = writeln!(writer, "{}", secret.as_str());
if written.is_ok() || written.is_err_and(|error| error.kind() == ErrorKind::BrokenPipe) {
return Ok(());
}
bail!("credential handoff could not write to stdout")
}
#[cfg(test)]View on GitHub (pinned to 433685b202)