Hmbown/CodeWhale · error
Custom provider ' ' API key not found. Set the environment…
Error message
Custom provider '{provider_name}' API key not found.
Set the environment variable {env_name} to your key, or add api_key to [providers.{provider_name}]. What it means
Thrown for a custom OpenAI-compatible provider when the configured api_key_env variable name exists but the key itself is missing at runtime. The config layer reads api_key_env from [providers.<name>], trims it, and if the env var it names is not set (or empty), it bails telling the developer exactly which variable to set. Custom providers must supply auth either inline or via a named env var.
Solutions
- Export the env variable named in the error with your API key
- Or add `api_key = "..."` directly under [providers.<name>] in ~/.codewhale/config.toml
- Verify the env var name in config matches the exported name exactly (case-sensitive, no stray whitespace)
Example fix
// before [providers.acme] api_key_env = "ACME_KEY" # ACME_KEY never exported // after (shell) export ACME_KEY="sk-..." # or in config.toml [providers.acme] api_key = "sk-..."
Defensive patterns
Strategy: validation
Validate before calling
// custom provider declares api_key_env = "ACME_KEY"
let ok = std::env::var("ACME_KEY").map(|v| !v.trim().is_empty()).unwrap_or(false);
if !ok { eprintln!("ACME_KEY is not set; export it or set api_key in [providers.acme]"); } Try / catch
match result {
Err(e) if e.to_string().contains("Custom provider") && e.to_string().contains("API key not found") => export_custom_key_and_retry(),
other => other?,
} Prevention
- Export the env var named by api_key_env before launching
- Load .env files in shells/CI where codewhale runs
- Match env var names exactly, including case
When it happens
Trigger: Using a custom provider that has api_key_env = "MY_KEY" in [providers.<name>] while MY_KEY is unset or empty in the environment.
Common situations: Env var defined in config but never exported; .env file not loaded in the shell/CI; key set under a different variable name than api_key_env declares; container images missing the secret.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Custom provider ' ' has no auth configured. Add api_key_env…
- Custom provider ' ' API key not found: the route binds…
- is not a well-formed Codewhale API key, so it was not sent…
- Managing API keys needs an interactive login. Run…
- OAuth bearer credentials are not an API key
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/57682df4338792e0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/config.rs:7449
credential_help_for_provider_route(provider, &self.active_route_base_url());
anyhow::bail!(
"Ollama Cloud API key not found. Get a key: {}. Run 'codewhale auth set --provider ollama', set OLLAMA_API_KEY, or add [providers.ollama] api_key in ~/.codewhale/config.toml.",
help.credential_url
.unwrap_or(codewhale_config::provider::OLLAMA_CLOUD_API_KEY_URL)
)
}
// Custom OpenAI-compatible endpoints (#1519): the key comes from the
// env var named by `[providers.<name>] api_key_env`. If we reached
// here it is unset/empty (and the endpoint is not loopback).
ApiProvider::Custom => {
let provider_name = self.provider.as_deref().unwrap_or("<name>");
match self
.provider_config_for(provider)
.and_then(|entry| entry.api_key_env.as_deref())
.map(str::trim)
.filter(|name| !name.is_empty())
{
Some(env_name) => anyhow::bail!(
"Custom provider '{provider_name}' API key not found.\n\
Set the environment variable {env_name} to your key, \
or add api_key to [providers.{provider_name}]."
),
None => anyhow::bail!(
"Custom provider '{provider_name}' has no auth configured.\n\
Add api_key_env = \"YOUR_ENV_VAR\" (or api_key) to \
[providers.{provider_name}] in ~/.codewhale/config.toml."
),
}
}
_ => anyhow::bail!("{}", missing_provider_api_key_message(provider)?),
}
}
/// Resolve the skills directory path.
#[must_use]
pub fn skills_dir(&self) -> PathBuf {View on GitHub (pinned to 73e0f67d83)