Hmbown/CodeWhale · error
custom provider base URL must be an http(s) URL with a host
Error message
custom provider base URL must be an http(s) URL with a host
What it means
The base URL must parse with reqwest::Url and use the http or https scheme with a host. Anything else (missing scheme, ftp://, no host) bails so malformed endpoints never reach the config. A distinct message ("custom provider base URL is invalid: {err}") is returned when reqwest itself fails to parse; this bail covers a parseable URL with the wrong scheme or no host.
Solutions
- Prefix the value with https:// (or http://) if the scheme is missing.
- Verify the URL parses and has an http/https scheme plus a host before calling.
- Check the error text to distinguish parse failure from wrong-scheme/no-host.
Example fix
// before persist_custom_provider(path, "my_gateway", "api.example.com/v1", ...)?; // after persist_custom_provider(path, "my_gateway", "https://api.example.com/v1", ...)?;
Defensive patterns
Strategy: validation
Validate before calling
use reqwest::Url;
let u = Url::parse(url.trim().trim_end_matches('/'))?;
if !matches!(u.scheme(), "http" | "https") || u.host_str().is_none() {
return Err(anyhow::anyhow!("must be http(s) URL with host"));
} Type guard
fn is_http_url(raw: &str) -> bool {
reqwest::Url::parse(raw.trim().trim_end_matches('/'))
.map(|u| matches!(u.scheme(), "http" | "https") && u.host_str().is_some())
.unwrap_or(false)
} Try / catch
match persist_custom_provider(path, name, &url, ...) {
Err(e) if e.to_string().contains("http(s) URL") || e.to_string().contains("base URL is invalid") => show_url_error(&e),
other => other,
} Prevention
- Always include the https:// scheme when entering endpoints.
- Pre-validate with reqwest::Url::parse in the UI.
- Reject non-http(s) schemes early.
When it happens
Trigger: Calling persist_custom_provider with e.g. "api.example.com/v1" (no scheme), "ftp://host", or a URL with no host component.
Common situations: Users omitting the https:// prefix; pasting a socket path or an internal hostname without a scheme.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- custom provider base URL is invalid
- custom provider base URL is required
- --base-url must use http or https
- browser URL cannot be empty
- Codewhale account API base URL must be an origin without a…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/4dfb761d15348399.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/config_persistence.rs:717
.chars()
.all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '_' | '-'))
{
bail!("custom provider name may only use letters, numbers, '-' and '_'");
}
Ok(value.to_string())
}
fn normalize_custom_provider_base_url(raw: &str) -> anyhow::Result<String> {
use anyhow::bail;
let value = raw.trim().trim_end_matches('/');
if value.is_empty() {
bail!("custom provider base URL is required");
}
let parsed = reqwest::Url::parse(value)
.map_err(|err| anyhow::anyhow!("custom provider base URL is invalid: {err}"))?;
if !matches!(parsed.scheme(), "http" | "https") || parsed.host_str().is_none() {
bail!("custom provider base URL must be an http(s) URL with a host");
}
Ok(value.to_string())
}
fn normalize_optional_custom_provider_field(raw: &str) -> Option<String> {
let value = raw.trim();
(!value.is_empty()).then(|| value.to_string())
}
pub(crate) fn persist_hotbar_bindings(
config_path: Option<&Path>,
bindings: &[codewhale_config::HotbarBindingToml],
) -> anyhow::Result<PathBuf> {
let path = config_toml_path(config_path)?;
mutate_config_document(&path, |doc| {
let table = doc.as_table_mut();
table.remove("hotbar");
if bindings.is_empty() {View on GitHub (pinned to 73e0f67d83)