Hmbown/CodeWhale · error · anyhow::Error
Codewhale account API base URL must not contain credentials
Error message
Codewhale account API base URL must not contain credentials
What it means
validate_api_base rejects any account API base URL containing userinfo (user:password@host) before it is ever used. Credentials embedded in URLs leak via logs, history, and error messages, and none of the cloud endpoints accept them, so this is an early hard stop with a clear message.
Source
Thrown at crates/cli/src/cloud.rs:764
writeln!(out, "Email: {}", printable(&user.email))?;
}
if !user.plan.trim().is_empty() {
writeln!(out, "Plan: {}", printable(&user.plan))?;
}
writeln!(out, "Profile: {}", printable(profile))?;
writeln!(out, "API: {api_base}")?;
Ok(())
}
struct ValidatedApiBase {
url: Url,
display: String,
}
fn validate_api_base(value: &str) -> Result<ValidatedApiBase> {
let mut url = Url::parse(value.trim()).context("invalid Codewhale account API base URL")?;
if !url.username().is_empty() || url.password().is_some() {
bail!("Codewhale account API base URL must not contain credentials");
}
if url.query().is_some() || url.fragment().is_some() {
bail!("Codewhale account API base URL must not contain a query or fragment");
}
if !matches!(url.path(), "" | "/") {
bail!("Codewhale account API base URL must be an origin without a path");
}
let host = url
.host_str()
.ok_or_else(|| anyhow!("Codewhale account API base URL must include a host"))?;
let allowed = url.scheme() == "https" || (url.scheme() == "http" && is_loopback_host(host));
if !allowed {
bail!(
"Codewhale account API base URL must use HTTPS (loopback HTTP is allowed for testing)"
);
}
url.set_path("/");
let display = url.as_str().trim_end_matches('/').to_string();View on GitHub (pinned to 0c42157ee5)
Solutions
- Remove the userinfo portion: use a plain origin such as https://api.codewhale.net.
- If the endpoint needs auth, that belongs in headers/tokens, not the base URL (Codewhale cloud auth is the OAuth session, not URL credentials).
- Check both the --api-base flag and the stored profile config for the stray credentials.
Example fix
# before --api-base https://user:secret@api.codewhale.net # after --api-base https://api.codewhale.net
Defensive patterns
Strategy: validation
Validate before calling
// Validate before passing to the CLI
fn base_url_is_safe(value: &str) -> bool {
url::Url::parse(value).map(|u| u.username().is_empty() && u.password().is_none()).unwrap_or(false)
} Type guard
fn is_credential_free_origin(u: &url::Url) -> bool {
u.username().is_empty() && u.password().is_none()
&& matches!(u.path(), "" | "/")
&& u.query().is_none() && u.fragment().is_none()
} Prevention
- Lint config for userinfo in URLs before deploy.
- Teach templates to emit origins only.
- Remember cloud auth is OAuth-session based; URLs never carry credentials.
When it happens
Trigger: Passing --api-base or config like https://user:pass@api.codewhale.net or http://admin:x@localhost:9000; copy-pasting a URL that includes basic-auth userinfo.
Common situations: Users templating authenticated internal URLs into the api-base setting, docs/examples that include userinfo placeholders, muscle memory from tools that support basic auth in the URL.
Related errors
- Codewhale account API base URL must use HTTPS (loopback HTTP
- The Codewhale service returned an unsafe verification URL
- Codewhale account API base URL must not contain a query or f
- Codewhale account API base URL must be an origin without a p
- The Codewhale service returned an unexpectedly large respons
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/5b6748c080e343d5.
Report an issue: GitHub.