{"record":{"id":"538a667e5f94bd0d","repo":"zeroclaw-labs/zeroclaw","slug":"providers-models-profile-name-uri-must-use-http","errorCode":null,"errorMessage":"providers.models.{profile_name}.uri must use http/https","messagePattern":"providers\\.models\\.(.+?)\\.uri must use http/https","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":21609,"sourceCode":"            let has_model = profile\n                .model\n                .as_deref()\n                .is_some_and(|v| !v.trim().is_empty());\n            if !has_uri && !has_api_key && !has_model {\n                ::zeroclaw_log::record!(WARN, ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note).with_outcome(::zeroclaw_log::EventOutcome::Unknown).with_attrs(::serde_json::json!({\"model_provider\": profile_name, \"profile_name\": profile_name})), \"providers.models. is empty (no uri / api_key / model). \\\n                     Skipping at runtime; run `zeroclaw quickstart` (or use the dashboard) \\\n                     to make this model_provider usable.\");\n                continue;\n            }\n\n            if let Some(uri) = profile.uri.as_deref().map(str::trim)\n                && !uri.is_empty()\n            {\n                let parsed = reqwest::Url::parse(uri).with_context(|| {\n                    format!(\"providers.models.{profile_name}.uri is not a valid URL\")\n                })?;\n                if !matches!(parsed.scheme(), \"http\" | \"https\") {\n                    anyhow::bail!(\"providers.models.{profile_name}.uri must use http/https\");\n                }\n            }\n\n            if let Some(temp) = profile.temperature {\n                validate_temperature(temp).map_err(|e| {\n                    ::zeroclaw_log::record!(\n                        WARN,\n                        ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)\n                            .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n                            .with_attrs(::serde_json::json!({\n                                \"profile\": profile_name,\n                                \"temperature\": temp,\n                                \"error\": format!(\"{}\", e),\n                            })),\n                        \"providers.models.<alias>.temperature rejected\"\n                    );\n                    anyhow::Error::msg(format!(\"providers.models.{profile_name}.temperature: {e}\"))\n                })?;","sourceCodeStart":21591,"sourceCodeEnd":21627,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L21591-L21627","documentation":"When a model profile under [providers.models] declares a non-empty uri, it must parse as a URL (via reqwest::Url::parse) and its scheme must be exactly http or https. A URL that fails to parse produces the earlier 'is not a valid URL' error; a parsable URL with any other scheme (file, unix, ws, ftp, or a mistyped scheme) reaches this bail. Schemeless strings like `localhost:11434` parse with scheme \"localhost\" and fail here too.","triggerScenarios":"Set a profile uri to \"file:///models/foo.gguf\", \"unix:///tmp/llm.sock\", \"ws://host:8080\", \"localhost:11434\" (no scheme), or a typo like \"httsp://api.example.com\".","commonSituations":"Pointing a profile at a local GGUF file or Unix socket, which this provider surface does not support; forgetting the scheme on local endpoints; using ws:// for streaming endpoints; template variables that render a bare host.","solutions":["Write an explicit http(s) URL — local daemons become `uri = \"http://localhost:11434\"`","Move file- or socket-backed models to whichever provider surface supports them; providers.models is HTTP-only","Fix scheme typos (httsp, http\\\\, hpp)","Re-run validation after each fix: the loop bails on the first bad profile, so fix profiles one at a time"],"exampleFix":"# before\n[providers.models.local]\nuri = \"localhost:11434\"\n\n# after\n[providers.models.local]\nuri = \"http://localhost:11434\"","handlingStrategy":"validation","validationCode":"fn http_url_precheck(cfg: &zeroclaw_config::Config) -> Result<(), String> {\n    for (name, profile) in &cfg.providers.models.entries {\n        if let Some(uri) = &profile.uri {\n            if uri.is_empty() { continue; }\n            match reqwest::Url::parse(uri) {\n                Ok(u) if matches!(u.scheme(), \"http\" | \"https\") => {}\n                _ => return Err(format!(\"providers.models.{name}.uri must use http/https\")),\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":"fn is_http_url(uri: &str) -> bool {\n    reqwest::Url::parse(uri).is_ok_and(|u| matches!(u.scheme(), \"http\" | \"https\"))\n}","tryCatchPattern":"if let Err(err) = config.validate() {\n    if err.to_string().contains(\"must use http/https\") {\n        // give the named profile an explicit http(s) URL; local daemons -> http://localhost:PORT\n    }\n}","preventionTips":["Always write the scheme, even for localhost","Reserve providers.models for HTTP endpoints; route file/socket backends elsewhere","Add a config-template lint that requires uri to start with http:// or https://"],"tags":["configuration","validation","providers","url","zeroclaw","rust"],"backgroundTag":"unsupported-url-scheme","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}