Hmbown/CodeWhale · error
custom provider name is required
Error message
custom provider name is required
What it means
normalize_custom_provider_id rejects an empty or whitespace-only custom provider name; persist_custom_provider calls it before writing the [providers.<name>] table, so a blank name can never create an unnamed provider entry.
Solutions
- Supply a non-empty name before calling persist_custom_provider.
- Trim and check the name in the caller and show a form-validation error.
Example fix
// before persist_custom_provider(path, "", &url, ...)?; // after let name = name.trim(); anyhow::ensure!(!name.is_empty(), "provider name required"); persist_custom_provider(path, name, &url, ...)?;
Defensive patterns
Strategy: validation
Validate before calling
let name = raw.trim();
if name.is_empty() { return Err(anyhow::anyhow!("provider name required")); } Type guard
fn valid_name(raw: &str) -> Option<&str> { let v = raw.trim(); (!v.is_empty()).then_some(v) } Try / catch
match persist_custom_provider(path, name, &url, ...) {
Err(e) if e.to_string().contains("name is required") => show_form_error("name required"),
other => other,
} Prevention
- Require the name field in forms/UIs.
- Trim input before submitting.
- Reject empty names at the CLI arg-parsing layer.
When it happens
Trigger: Calling persist_custom_provider with an empty or whitespace-only provider name.
Common situations: A UI form submitted with the name field blank; a script interpolating an unset variable into the name argument.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- custom provider base URL is required
- agent profile cannot be empty
- BYDAY cannot be empty for WEEKLY schedules
- continual harness entry id cannot be empty
- custom provider base URL is invalid
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/0052f02054be702f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/config_persistence.rs:690
unset_document_value(doc, &[entry[0], entry[1], "api_key_env"])?;
if provider_id == "ds4" && crate::config::base_url_uses_local_host(&base_url) {
set_document_value(doc, &[entry[0], entry[1], "auth_mode"], "none")?;
} 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;View on GitHub (pinned to 73e0f67d83)