{"record":{"id":"c980c87c8c4b5867","repo":"aaif-goose/goose","slug":"invalid-base-url-c980c8","errorCode":null,"errorMessage":"Invalid base URL '{}': {}","messagePattern":"Invalid base URL '(.+?)': (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/goose-providers/src/openai.rs","lineNumber":893,"sourceCode":"    }\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                }\n                None\n            }\n        }\n    };\n\n    let normalized_base_url = ensure_url_scheme(&config.base_url);\n    let url = url::Url::parse(&normalized_base_url)\n        .map_err(|e| anyhow::anyhow!(\"Invalid base URL '{}': {}\", config.base_url, e))?;\n\n    let host = url[..url::Position::BeforePath].to_string();\n    let base_path = if let Some(ref explicit_path) = config.base_path {\n        explicit_path.trim_start_matches('/').to_string()\n    } else {\n        derive_base_path(url.path())\n    };\n\n    let timeout_secs = config.timeout_seconds.unwrap_or(DEFAULT_TIMEOUT_SECONDS);\n\n    let auth = match api_key {\n        Some(key) if !key.is_empty() => AuthMethod::BearerToken(key),\n        _ => AuthMethod::NoAuth,\n    };\n    let mut api_client = ApiClient::with_timeout_and_tls(\n        host,\n        auth,\n        std::time::Duration::from_secs(timeout_secs),","sourceCodeStart":875,"sourceCodeEnd":911,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-providers/src/openai.rs#L875-L911","documentation":"Thrown by from_declarative_config when the base_url field of a declarative provider cannot be parsed as a URL. Like error 280, the value passes through ensure_url_scheme first (http for loopback hosts, https otherwise), then url::Url::parse; failure is reported with the original config value and the parser error. It applies to provider definitions in config files rather than the OPENAI_BASE_URL env var.","triggerScenarios":"A provider entry whose base_url contains spaces, an invalid port, a missing host, or malformed percent-encoding, e.g. 'base_url: localhost 8080/v1' or 'base_url: https://[broken'.","commonSituations":"Hand-edited YAML introducing typos, URLs split across lines by accident, templated configs where a placeholder ({{host}}) was never substituted, or a trailing colon/backslash after the host.","solutions":["Inspect the base_url value in the config file and fix the syntax error named by the parser message","Include the scheme explicitly and verify host and port (https://gateway.example.com:8443/v1)","Check for unsubstituted template placeholders or accidental line-wraps in the YAML string","Test the URL standalone (curl or url::Url::parse) before restarting goose"],"exampleFix":"# before\nbase_url: \"https://my gateway.example.com/v1\"\n\n# after\nbase_url: \"https://my-gateway.example.com/v1\"","handlingStrategy":"validation","validationCode":"url::Url::parse(&ensure_url_scheme(&cfg.base_url))\n    .map_err(|e| anyhow::anyhow!(\"fix base_url in provider config: {e}\"))?;","typeGuard":null,"tryCatchPattern":"match OpenAiProviderBuilder::from_declarative_config(cfg.clone(), tls, resolver) {\n    Ok(b) => b,\n    Err(e) if e.to_string().contains(\"Invalid base URL\") => {\n        eprintln!(\"provider '{}' has a bad base_url: {e}\", cfg.name);\n        std::process::exit(2);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Template-substitute base_url before deploying configs and assert no '{{' remains","Smoke-test configs by parsing them in a unit test"],"tags":["config","url","provider","validation"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}