zeroclaw-labs/zeroclaw · error · anyhow::Error

Custom model_provider `{prefix}:<url>` requires a URL beginn

Error message

Custom model_provider `{prefix}:<url>` requires a URL beginning with http:// or https://. Set `[providers.models.custom.<alias>] uri = "https://your-api.com"` or pass a valid URL.

What it means

create_model_provider_inner parses inline provider names of the form `custom:<url>` and `anthropic-custom:<url>`. When the part after the colon is empty (after trimming) or does not start with http:// or https://, construction fails immediately, before any dispatch or network activity. The message suggests both the inline form and the explicit profile form with a `uri` field.

Source

Thrown at crates/zeroclaw-providers/src/lib.rs:1281

}

/// Factory: create model_provider with optional base URL and runtime options.
#[allow(clippy::too_many_lines)]
fn create_model_provider_inner(
    config: Option<&zeroclaw_config::schema::Config>,
    raw_name: &str,
    alias: &str,
    api_key: Option<&str>,
    api_url: Option<&str>,
    options: &ModelProviderRuntimeOptions,
) -> anyhow::Result<Box<dyn ModelProvider>> {
    if let Some(idx) = raw_name.find(':') {
        let prefix = &raw_name[..idx];
        let url = raw_name[idx + 1..].trim();
        if matches!(prefix, "custom" | "anthropic-custom")
            && (url.is_empty() || !(url.starts_with("http://") || url.starts_with("https://")))
        {
            anyhow::bail!(
                "Custom model_provider `{prefix}:<url>` requires a URL beginning with http:// or https://. \
                 Set `[providers.models.custom.<alias>] uri = \"https://your-api.com\"` or pass a valid URL."
            );
        }
    }
    let (split_name, split_url) = split_v2_colon_url(raw_name);
    let legacy_kimi_code = is_legacy_kimi_code_alias(split_name);
    let api_url = api_url.or(split_url);
    let name = canonicalize_v2_model_provider_name(split_name);
    let provider_kind = options
        .provider_kind
        .as_deref()
        .map(str::trim)
        .filter(|value| !value.is_empty())
        .map(canonicalize_v2_model_provider_name)
        .unwrap_or(name);

    // V2 spelled OpenAI Codex as `openai-codex` / `openai_codex` / `codex`.

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Include the scheme: `custom:https://api.example.com/v1`
  2. Prefer the explicit profile: `[providers.models.custom.<alias>]` with `uri = "https://your-api.com"`, then reference the alias
  3. Use https:// unless the endpoint is a local plaintext proxy that genuinely requires http://

Example fix

# before
model_provider = "custom:my-gateway.internal/v1"

# after
model_provider = "custom:https://my-gateway.internal/v1"
Defensive patterns

Strategy: validation

Validate before calling

fn custom_provider_name_ok(raw: &str) -> bool {
    match raw.split_once(':') {
        Some((prefix, url)) if matches!(prefix, "custom" | "anthropic-custom") => {
            let url = url.trim();
            !url.is_empty() && (url.starts_with("http://") || url.starts_with("https://"))
        }
        _ => true,
    }
}

Type guard

fn is_valid_custom_url(raw: &str) -> Option<(&str, &str)> {
    let (prefix, url) = raw.split_once(':')?;
    let url = url.trim();
    if matches!(prefix, "custom" | "anthropic-custom")
        && (url.starts_with("http://") || url.starts_with("https://"))
    { Some((prefix, url)) } else { None }
}

Try / catch

if !custom_provider_name_ok(&model_provider) {
    return Err(format!("invalid custom provider name `{model_provider}`; expected custom:https://..."));
}
create_resilient_model_provider(&model_provider, api_key, api_url, &reliability).await

Prevention

When it happens

Trigger: model_provider = "custom:api.example.com/v1" (missing scheme); "custom:" (empty URL); "anthropic-custom:ftp://host" (wrong scheme); a template concatenation leaving a trailing colon.

Common situations: Moving from the profile `uri` field to the inline name form and dropping the scheme; copy-paste that loses `https://`; environment-variable-built provider names with empty URL segments.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/785e96d501ed48c5. Report an issue: GitHub.