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 parses the user-supplied account API base URL and rejects URLs embedding userinfo (username or password). Credentials in the base URL would be sent with every request and can leak into logs and config, so they are prohibited outright.
Solutions
- Strip the user:password@ portion and use the host-only origin: https://api.example.com.
- Supply credentials another way if the endpoint needs them (headers, a proxy you control) — never in the base URL.
- Re-run the command with the cleaned origin.
Example fix
// before CODEWHALE_API_BASE=https://user:secret@api.example.com // after CODEWHALE_API_BASE=https://api.example.com
Defensive patterns
Strategy: validation
Validate before calling
fn has_no_credentials(url: &str) -> bool {
url::Url::parse(url.trim())
.map(|u| u.username().is_empty() && u.password().is_none())
.unwrap_or(false)
} Prevention
- Never embed user:password in a base URL.
- Strip userinfo before storing the base URL in config/env.
- If an endpoint needs basic auth, use a proxy or header-based auth instead.
- Review connection-string-derived values for embedded credentials.
When it happens
Trigger: Setting the account API base URL (env/config/flag) to a URL containing user:pass@host userinfo, e.g. https://admin:secret@api.example.com.
Common situations: Pasting an internal service URL that includes basic-auth credentials; templating base URLs from connection strings that embed credentials.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- --base-url must use http or https
- Codewhale account API base URL must be an origin without a…
- Codewhale account API base URL must not contain a query or…
- Codewhale account API base URL must use HTTPS (loopback…
- `codewhale account` does not accept the global `--api-key`…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/5b6748c080e343d5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/cloud.rs:1018
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 73e0f67d83)