{"record":{"id":"c0b5378bd9f2e408","repo":"aaif-goose/goose","slug":"invalid-openai-base-url","errorCode":null,"errorMessage":"Invalid OPENAI_BASE_URL '{}': {}","messagePattern":"Invalid OPENAI_BASE_URL '(.+?)': (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/goose-providers/src/openai.rs","lineNumber":113,"sourceCode":"    let bare_host = if let Some(rest) = host_part.strip_prefix('[') {\n        rest.split(']').next().unwrap_or(rest)\n    } else {\n        host_part.split(':').next().unwrap_or(host_part)\n    };\n    let is_local = bare_host == \"localhost\"\n        || bare_host == \"127.0.0.1\"\n        || bare_host == \"0.0.0.0\"\n        || bare_host == \"::1\";\n\n    let scheme = if is_local { \"http\" } else { \"https\" };\n    format!(\"{}://{}\", scheme, trimmed)\n}\n\npub fn parse_openai_base_url(raw_url: &str) -> Result<OpenAiBaseUrlParts> {\n    let raw_url = ensure_url_scheme(raw_url);\n    let raw_url = raw_url.as_str();\n    let parsed = url::Url::parse(raw_url)\n        .map_err(|e| anyhow::anyhow!(\"Invalid OPENAI_BASE_URL '{}': {}\", raw_url, e))?;\n\n    let authority = parsed[..url::Position::BeforePath].to_string();\n    let query_params: Vec<(String, String)> = parsed\n        .query_pairs()\n        .map(|(k, v)| (k.into_owned(), v.into_owned()))\n        .collect();\n\n    let path = parsed.path().trim_end_matches('/');\n    if path.is_empty() || path == \"/\" {\n        return Ok((authority, query_params, true));\n    }\n\n    if path == \"/v1\" {\n        return Ok((authority, query_params, true));\n    }\n    if let Some(prefix) = path.strip_suffix(\"/v1\") {\n        return Ok((format!(\"{}{}\", authority, prefix), query_params, true));\n    }","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-providers/src/openai.rs#L95-L131","documentation":"Thrown by parse_openai_base_url in goose-providers when the OPENAI_BASE_URL value cannot be parsed as a URL. The value is first normalized by ensure_url_scheme (http:// is assumed for localhost/127.0.0.1/0.0.0.0/::1 hosts, https:// otherwise), then handed to url::Url::parse; any parse failure is reported with the normalized URL and the underlying url crate error. This is a configuration-input error, not a network error.","triggerScenarios":"Setting OPENAI_BASE_URL to a string that is not a valid absolute URL after scheme injection: spaces or control characters ('my host:8080'), an invalid port ('http://proxy:notaport'), a missing host ('http://:8080'), garbage characters ('ht!tp://x'), or unencoded credentials containing special characters like '@' or spaces in the userinfo part.","commonSituations":"Copy-pasting a proxy or gateway URL with quotes/spaces around it, typos in the host, a base URL with a password containing reserved characters that must be percent-encoded, or CI environments where the env var is assembled from other variables and ends up empty or malformed.","solutions":["Print the exact value with quoting (e.g. printf '[%s]\\n' \"$OPENAI_BASE_URL\") and fix any typo, stray space, quote, or newline","Specify the scheme explicitly (https://host or http://localhost:port) and make sure the host is non-empty and the port is numeric","Percent-encode special characters in userinfo (user:pass%40word@host) or move credentials to the API key variable","Validate the URL with a one-liner before starting goose, e.g. python3 -c \"from urllib.parse import urlparse; urlparse('YOUR_URL')\" or url::Url::parse in a test"],"exampleFix":"# before\nexport OPENAI_BASE_URL=\"my proxy.example.com/v1\"\n\n# after\nexport OPENAI_BASE_URL=\"https://my-proxy.example.com/v1\"","handlingStrategy":"validation","validationCode":"use url::Url;\n\nfn valid_base_url(raw: &str) -> bool {\n    Url::parse(raw).is_ok()\n        || {\n            let scheme = if raw.starts_with(\"http\") { String::new() } else { \"https://\".to_string() };\n            Url::parse(&format!(\"{scheme}{raw}\")).is_ok()\n        }\n}\n\nfn main() {\n    let raw = std::env::var(\"OPENAI_BASE_URL\").expect(\"OPENAI_BASE_URL set\");\n    assert!(valid_base_url(&raw), \"fix OPENAI_BASE_URL before starting\");\n}","typeGuard":null,"tryCatchPattern":"match parse_openai_base_url(&raw) {\n    Ok(parts) => { /* proceed */ }\n    Err(e) => {\n        eprintln!(\"configuration error in OPENAI_BASE_URL: {e}\");\n        std::process::exit(2); // fail fast on config, do not retry\n    }\n}","preventionTips":["Set OPENAI_BASE_URL with an explicit scheme and quoted values in shell profiles","Add a startup check that Url::parse succeeds before any request is made","Percent-encode credentials embedded in URLs"],"tags":["config","url","openai","environment","validation"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}