aaif-goose/goose · error · anyhow::Error
Invalid OPENAI_BASE_URL '{}': {}
Error message
Invalid OPENAI_BASE_URL '{}': {} What it means
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.
Source
Thrown at crates/goose-providers/src/openai.rs:113
let bare_host = if let Some(rest) = host_part.strip_prefix('[') {
rest.split(']').next().unwrap_or(rest)
} else {
host_part.split(':').next().unwrap_or(host_part)
};
let is_local = bare_host == "localhost"
|| bare_host == "127.0.0.1"
|| bare_host == "0.0.0.0"
|| bare_host == "::1";
let scheme = if is_local { "http" } else { "https" };
format!("{}://{}", scheme, trimmed)
}
pub fn parse_openai_base_url(raw_url: &str) -> Result<OpenAiBaseUrlParts> {
let raw_url = ensure_url_scheme(raw_url);
let raw_url = raw_url.as_str();
let parsed = url::Url::parse(raw_url)
.map_err(|e| anyhow::anyhow!("Invalid OPENAI_BASE_URL '{}': {}", raw_url, e))?;
let authority = parsed[..url::Position::BeforePath].to_string();
let query_params: Vec<(String, String)> = parsed
.query_pairs()
.map(|(k, v)| (k.into_owned(), v.into_owned()))
.collect();
let path = parsed.path().trim_end_matches('/');
if path.is_empty() || path == "/" {
return Ok((authority, query_params, true));
}
if path == "/v1" {
return Ok((authority, query_params, true));
}
if let Some(prefix) = path.strip_suffix("/v1") {
return Ok((format!("{}{}", authority, prefix), query_params, true));
}View on GitHub (pinned to 3810898a74)
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
Example fix
# before export OPENAI_BASE_URL="my proxy.example.com/v1" # after export OPENAI_BASE_URL="https://my-proxy.example.com/v1"
Defensive patterns
Strategy: validation
Validate before calling
use url::Url;
fn valid_base_url(raw: &str) -> bool {
Url::parse(raw).is_ok()
|| {
let scheme = if raw.starts_with("http") { String::new() } else { "https://".to_string() };
Url::parse(&format!("{scheme}{raw}")).is_ok()
}
}
fn main() {
let raw = std::env::var("OPENAI_BASE_URL").expect("OPENAI_BASE_URL set");
assert!(valid_base_url(&raw), "fix OPENAI_BASE_URL before starting");
} Try / catch
match parse_openai_base_url(&raw) {
Ok(parts) => { /* proceed */ }
Err(e) => {
eprintln!("configuration error in OPENAI_BASE_URL: {e}");
std::process::exit(2); // fail fast on config, do not retry
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- {} must be at least 4096
- Invalid base URL '{}': {}
- External ACP backend URL is required
- External ACP backend URL must use http: or https:, got ${url
- External ACP backend URL must not include query parameters o
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/c0b5378bd9f2e408.
Report an issue: GitHub.