Hmbown/CodeWhale · error · anyhow::Error
Codewhale account API base URL must not contain a query or f
Error message
Codewhale account API base URL must not contain a query or fragment
What it means
validate_api_base requires a pure origin: any query string (?...) or fragment (#...) in the configured API base is rejected. The base is combined with fixed endpoint paths by the transport, so queries/fragments would either be silently dropped or corrupt the joined URL; rejecting them surfaces config typos immediately.
Source
Thrown at crates/cli/src/cloud.rs:767
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();
Ok(ValidatedApiBase { url, display })
}
View on GitHub (pinned to 0c42157ee5)
Solutions
- Strip everything after the host[:port]: use https://api.codewhale.net.
- Auth goes through `codewhale account login`, never query params.
- Re-check the stored profile config after fixing the flag so the bad value does not persist.
Example fix
# before --api-base 'https://api.codewhale.net?source=cli' # after --api-base https://api.codewhale.net
Defensive patterns
Strategy: validation
Validate before calling
fn is_bare_origin(u: &url::Url) -> bool {
u.query().is_none() && u.fragment().is_none() && matches!(u.path(), "" | "/")
} Type guard
fn is_valid_api_base(value: &str) -> bool {
url::Url::parse(value.trim()).map(|u| {
is_bare_origin(&u) && u.username().is_empty() && u.password().is_none()
&& (u.scheme() == "https" || (u.scheme() == "http" && is_loopback(u.host_str().unwrap_or(""))))
}).unwrap_or(false)
} Prevention
- Store only origins in api-base config.
- Never append tokens as query params.
- Validate the value in CI config checks before it reaches the CLI.
When it happens
Trigger: Configuring --api-base 'https://api.codewhale.net?token=x' or 'https://host/#section'; pasting a deep link (with tracking params) instead of the bare origin.
Common situations: Copy-pasting a URL from a browser address bar that carries params, appending API keys as query params out of habit, leftover fragments from documentation anchors.
Related errors
- Codewhale account API base URL must be an origin without a p
- Codewhale account API base URL must not contain credentials
- Codewhale account API base URL must use HTTPS (loopback HTTP
- The Codewhale service returned an unsafe verification URL
- The Codewhale service returned an unexpectedly large respons
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/9c40b44315475ff4.
Report an issue: GitHub.