Hmbown/CodeWhale · error
custom provider name is reserved
Error message
custom provider name is reserved
What it means
normalize_custom_provider_id rejects the reserved sentinel name '__custom__', which marks the custom-provider slot internally and must never become a real provider id; using it as a name would collide with the sentinel.
Solutions
- Pick a different name for the provider.
- In UIs, treat "__custom__" as an unset placeholder and require a real name before saving.
Example fix
// before persist_custom_provider(path, "__custom__", &url, ...)?; // after persist_custom_provider(path, "my_gateway", &url, ...)?;
Defensive patterns
Strategy: validation
Validate before calling
if name.trim() == "__custom__" { return Err(anyhow::anyhow!("reserved name")); } Type guard
fn is_reserved(name: &str) -> bool { name.trim() == "__custom__" } Try / catch
match persist_custom_provider(path, name, &url, ...) {
Err(e) if e.to_string().contains("reserved") => prompt_for_different_name(),
other => other,
} Prevention
- Never use "__custom__" as a provider name; it is a placeholder sentinel.
- Replace UI placeholder values with real names before saving.
When it happens
Trigger: Calling persist_custom_provider with a name exactly "__custom__" (after trimming).
Common situations: A UI passes through its internal placeholder value when the user never replaced it with a real name.
Related errors
- custom provider base URL is invalid
- custom provider base URL is required
- custom provider base URL must be an http(s) URL with a host
- custom provider id cannot be empty
- custom provider name is required
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/713d214344a13e0f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/config_persistence.rs:693
} else {
unset_document_value(doc, &[entry[0], entry[1], "auth_mode"])?;
}
}
}
Ok(())
})?;
Ok(path)
}
fn normalize_custom_provider_id(raw: &str) -> anyhow::Result<String> {
use anyhow::bail;
let value = raw.trim();
if value.is_empty() {
bail!("custom provider name is required");
}
if value == "__custom__" {
bail!("custom provider name is reserved");
}
if crate::config::ApiProvider::parse(value).is_some() {
bail!("custom provider name must not shadow a built-in provider");
}
if !value
.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() {View on GitHub (pinned to 73e0f67d83)