{"record":{"id":"2549c05b97cebf10","repo":"zeroclaw-labs/zeroclaw","slug":"providers-models-ollama-alias-model-uses-cloud","errorCode":null,"errorMessage":"providers.models.ollama.{alias}.model uses ':cloud', but uri is local or unset. Set uri to a remote Ollama endpoint (for example https://ollama.com).","messagePattern":"providers\\.models\\.ollama\\.(.+?)\\.model uses ':cloud', but uri is local or unset\\. Set uri to a remote Ollama endpoint \\(for example https://ollama\\.com\\)\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":21671,"sourceCode":"                    .with_outcome(::zeroclaw_log::EventOutcome::Unknown)\n                    .with_attrs(::serde_json::json!({\"path\": w.path, \"code\": w.code})),\n                &format!(\"{}\", w.message)\n            );\n        }\n\n        // Ollama cloud-routing safety checks\n        for (alias, cfg) in &self.providers.models.ollama {\n            let entry = &cfg.base;\n            if !entry\n                .model\n                .as_deref()\n                .is_some_and(|model| model.trim().ends_with(\":cloud\"))\n            {\n                continue;\n            }\n\n            if is_local_ollama_endpoint(entry.uri.as_deref()) {\n                anyhow::bail!(\n                    \"providers.models.ollama.{alias}.model uses ':cloud', but uri is local or unset. Set uri to a remote Ollama endpoint (for example https://ollama.com).\"\n                );\n            }\n            if is_official_ollama_cloud_endpoint(entry.uri.as_deref())\n                && !has_ollama_cloud_credential(entry.api_key.as_deref())\n            {\n                anyhow::bail!(\n                    \"providers.models.ollama.{alias}.model uses ':cloud', but no API key is configured. Set api_key on [providers.models.ollama.{alias}] (or via the schema-mirror grammar: ZEROCLAW_providers__models__ollama__{alias}__api_key=<value>).\"\n                );\n            }\n        }\n\n        // Microsoft 365\n        if self.microsoft365.enabled {\n            let tenant = self\n                .microsoft365\n                .tenant_id\n                .as_deref()","sourceCodeStart":21653,"sourceCodeEnd":21689,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L21653-L21689","documentation":"For every [providers.models.ollama.<alias>] whose model name ends with ':cloud', the uri must not be unset, empty, or point at a local host (localhost, 127.0.0.1, ::1, 0.0.0.0 — is_local_ollama_endpoint, schema.rs:19363). The ':cloud' suffix routes requests to Ollama Cloud, so a local or unset endpoint contradicts the routing and would silently hit a local daemon that lacks the model. Non-cloud model names skip these checks entirely.","triggerScenarios":"Add `model = \"gpt-oss:cloud\"` while leaving uri unset (treated as local), or keep `uri = \"http://127.0.0.1:11434\"` from an existing local setup after switching the model tag to a :cloud name.","commonSituations":"Trying Ollama Cloud on a machine that already runs the local daemon by only changing the model tag; shared alias templates that pre-fill the local URL; switching an alias between local and cloud without touching uri.","solutions":["Set a remote Ollama endpoint on the failing alias: `uri = \"https://ollama.com\"`","If you actually meant the local daemon, remove the ':cloud' suffix from model","After setting the remote uri, also set api_key — the official ollama.com endpoint triggers the next credential check","Check each alias separately; the loop reports one alias at a time"],"exampleFix":"# before\n[providers.models.ollama.default]\nmodel = \"gpt-oss:cloud\"\nuri = \"http://127.0.0.1:11434\"\n\n# after\n[providers.models.ollama.default]\nmodel = \"gpt-oss:cloud\"\nuri = \"https://ollama.com\"\napi_key = \"<ollama-cloud-key>\"","handlingStrategy":"validation","validationCode":"fn is_local_host(uri: Option<&str>) -> bool {\n    let Some(raw) = uri.map(str::trim).filter(|v| !v.is_empty()) else { return true; };\n    reqwest::Url::parse(raw).ok()\n        .and_then(|u| u.host_str().map(|h| h.to_ascii_lowercase()))\n        .is_some_and(|h| matches!(h.as_str(), \"localhost\" | \"127.0.0.1\" | \"::1\" | \"0.0.0.0\"))\n}\n\nfn ollama_cloud_precheck(cfg: &zeroclaw_config::Config) -> Result<(), String> {\n    for (alias, entry) in &cfg.providers.models.ollama {\n        let cloud = entry.base.model.as_deref().is_some_and(|m| m.trim().ends_with(\":cloud\"));\n        if cloud && is_local_host(entry.base.uri.as_deref()) {\n            return Err(format!(\"alias {alias}: :cloud model with local/unset uri\"));\n        }\n    }\n    Ok(())\n}","typeGuard":"fn cloud_model_has_remote_uri(model: Option<&str>, uri: Option<&str>) -> bool {\n    !model.is_some_and(|m| m.trim().ends_with(\":cloud\")) || !is_local_host(uri)\n}","tryCatchPattern":"if let Err(err) = config.validate() {\n    if err.to_string().contains(\":cloud\") && err.to_string().contains(\"uri is local\") {\n        // set uri = \"https://ollama.com\" on the named alias, or drop the :cloud suffix\n    }\n}","preventionTips":["Treat model tag and uri as one unit: changing either forces re-checking both","Template cloud aliases with the remote uri baked in, separate from local aliases","Add a pre-deploy grep for ':cloud' entries lacking a remote uri"],"tags":["configuration","validation","ollama","providers","zeroclaw","rust"],"backgroundTag":"ollama-cloud-misconfigured","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}