{"record":{"id":"f43856bd8265ceeb","repo":"aaif-goose/goose","slug":"invalid-base-url-f43856","errorCode":null,"errorMessage":"Invalid base URL '{}': {}","messagePattern":"Invalid base URL '(.+?)': (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/goose-providers/src/ollama.rs","lineNumber":306,"sourceCode":"        return Err(anyhow::anyhow!(\n            \"Provider '{}' has dynamic_models: false but no static models listed; \\\n             at least one entry in `models` is required.\",\n            config.name\n        ));\n    }\n\n    let timeout = Duration::from_secs(config.timeout_seconds.unwrap_or(OLLAMA_TIMEOUT));\n\n    let base_has_scheme =\n        config.base_url.starts_with(\"http://\") || config.base_url.starts_with(\"https://\");\n    let base = if base_has_scheme {\n        config.base_url.clone()\n    } else {\n        format!(\"http://{}\", config.base_url)\n    };\n\n    let mut base_url = Url::parse(&base)\n        .map_err(|e| anyhow::anyhow!(\"Invalid base URL '{}': {}\", config.base_url, e))?;\n\n    let is_localhost = matches!(base_url.host_str(), Some(\"localhost\" | \"127.0.0.1\" | \"::1\"));\n\n    if base_url.port().is_none() && !base_has_scheme && is_localhost {\n        base_url\n            .set_port(Some(OLLAMA_DEFAULT_PORT))\n            .map_err(|_| anyhow::anyhow!(\"Failed to set default port\"))?;\n    }\n\n    let api_key = if config.api_key_env.is_empty() {\n        None\n    } else {\n        match key_resolver.resolve_key(config.api_key_env.as_str()) {\n            Ok(key) => Some(key),\n            Err(err) => {\n                if config.requires_auth {\n                    anyhow::bail!(\"missing required key {}: {}\", config.api_key_env, err);\n                }","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-providers/src/ollama.rs#L288-L324","documentation":"Building the Ollama client, goose normalizes base_url: if it doesn't start with http:// or https:// it prepends http://, then parses with Url::parse. This error means parsing still failed — most commonly because base_url is empty ('http://' alone yields an empty-host parse error), or contains spaces, an invalid port (e.g. ':1143x'), or other characters the URL grammar rejects. Unlike the generic ApiClient error, this message echoes the original configured value.","triggerScenarios":"A declarative Ollama config with \"base_url\": \"\" (the classic case: field omitted/emptied by a template), 'base_url\": \"my host:11434\" (space), '\"ollama@server\"', or a malformed port like 'localhost:114_34'. Note localhost URLs without a port automatically get OLLAMA_DEFAULT_PORT (11434) applied, so that part needs no fixing.","commonSituations":"Config templating leaves an empty placeholder; users assume 'localhost' is enough without scheme and mangle it further; values pasted from docs pick up smart quotes or trailing whitespace; YAML unquoted strings containing ':#' sequences.","solutions":["Set a concrete URL: \"base_url\": \"http://localhost:11434\" (scheme optional for localhost, port auto-defaulted there) — but never empty","Check the echoed value in the message for spaces, smart quotes, or missing pieces, and quote the value in YAML/JSON","If pointing at a remote server, include scheme and port: \"https://ollama.internal.example.com:11434\""],"exampleFix":"// before\n{ \"name\": \"my-ollama\", \"engine\": \"ollama\", \"base_url\": \"\" }\n\n// after\n{ \"name\": \"my-ollama\", \"engine\": \"ollama\", \"base_url\": \"http://localhost:11434\" }","handlingStrategy":"validation","validationCode":"fn ollama_base_url_ok(raw: &str) -> anyhow::Result<url::Url> {\n    let with_scheme = if raw.starts_with(\"http://\") || raw.starts_with(\"https://\") {\n        raw.to_string()\n    } else {\n        format!(\"http://{}\", raw)\n    };\n    url::Url::parse(&with_scheme).map_err(|e| anyhow::anyhow!(\"base_url '{raw}': {e}\"))\n}","typeGuard":null,"tryCatchPattern":"// Mirror goose's normalization at config-load time so users get the error at\n// startup with the offending value echoed:\nlet base = ollama_base_url_ok(cfg.base_url.trim())?;","preventionTips":["Always write the full URL including scheme (http://localhost:11434) in configs","Reject empty base_url at config-load time with a clear message","Lint provider JSON for whitespace/smart quotes in URL fields"],"tags":["ollama","url","json-config","validation"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}