Hmbown/CodeWhale · error
Custom endpoint credentials for
Error message
Custom endpoint credentials for {route_name} must be bound explicitly. Ambient provider credentials are not sent to {}. Add api_key or api_key_env to this provider route, or pass --api-key with --base-url. What it means
Custom (--base-url / custom endpoint) provider routes must carry their own explicit credentials. Codewhale will not forward ambient provider credentials (keys meant for the official provider endpoint) to a user-supplied custom base URL, so the route fails at config resolution before any request leaves the machine.
Solutions
- Add api_key = "..." to the [providers.<route_name>] table in ~/.codewhale/config.toml.
- Or add api_key_env = "YOUR_ENV_VAR" to the route and export that variable.
- Or pass --api-key together with --base-url on the command line.
Example fix
// before [providers.my-proxy] base_url = "https://internal.corp/v1" // after [providers.my-proxy] base_url = "https://internal.corp/v1" api_key_env = "MY_PROXY_KEY"
Defensive patterns
Strategy: validation
Validate before calling
fn custom_endpoint_has_creds(p: &ProviderCfg) -> Result<(), String> {
if p.base_url.is_some() && p.api_key.is_none() && p.api_key_env.is_none() {
Err(format!("provider '{}' has a custom base_url but no api_key/api_key_env", p.name))
} else { Ok(()) }
} Try / catch
match result {
Err(e) if e.to_string().contains("must be bound explicitly") => {
eprintln!("add api_key or api_key_env to this route, or pass --api-key with --base-url");
}
other => other?,
} Prevention
- Always pair a custom --base-url with an explicit api_key or api_key_env in the same route.
- Never assume ambient provider keys follow a request to a custom endpoint — that is blocked by design.
- Smoke-test new custom routes with one cheap request before relying on them.
When it happens
Trigger: A provider route is marked custom_endpoint (custom base URL via [providers.<name>] base_url or --base-url) while its config has neither api_key nor api_key_env and no --api-key was passed.
Common situations: Pointing an OpenAI-compatible proxy/gateway at codewhale but forgetting to attach the proxy's key; moving a working official-provider config onto a self-hosted relay and assuming the existing ambient key still applies.
Related errors
- a CNB access token is not configured in the Codewhale…
- api_key cannot be empty string
- bundle URLs may not include credentials
- CF_ACCOUNT_ID and CF_API_TOKEN are required
- Codewhale-owned credential file DACL is not…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/649cf5e0d257f159.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/config.rs:7313
// The Codewhale API always authenticates. It is not a self-hosted
// runtime, and a loopback `CODEWHALE_API_BASE` is a test origin for
// the same authenticated contract — never a keyless one. Without this
// the loopback arm below returned an empty key and the request went
// out with no `Authorization` header at all.
if provider != ApiProvider::Codewhale
&& !auth_mode_requires_api_key(auth_mode.as_deref())
&& (provider_route_is_keyless_self_hosted(provider, &self.active_route_base_url())
|| base_url_uses_local_host(&self.active_route_base_url()))
{
return Ok(String::new());
}
if custom_endpoint {
let route_name = self
.provider
.as_deref()
.unwrap_or_else(|| provider.as_str());
anyhow::bail!(
"Custom endpoint credentials for {route_name} must be bound explicitly. Ambient provider credentials are not sent to {}. Add api_key or api_key_env to this provider route, or pass --api-key with --base-url.",
self.active_route_base_url()
);
}
match provider {
ApiProvider::Codewhale => anyhow::bail!(
"Codewhale API key not found, so no request was sent.\n\
\n\
The Codewhale API authenticates every model with one account \
API key carrying the `models:infer` scope.\n\
\n\
1. Create one and save it on this machine:\n\
codewhale account api-keys create --name <name> --scope models:infer --use\n\
2. Or export it for this shell:\n\
export CODEWHALE_API_KEY=cwc_key_...\n\
\n\
You can also create a key at {} and put it in \View on GitHub (pinned to 73e0f67d83)