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

  1. Print the exact value with quoting (e.g. printf '[%s]\n' "$OPENAI_BASE_URL") and fix any typo, stray space, quote, or newline
  2. Specify the scheme explicitly (https://host or http://localhost:port) and make sure the host is non-empty and the port is numeric
  3. Percent-encode special characters in userinfo (user:pass%40word@host) or move credentials to the API key variable
  4. 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

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


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/c0b5378bd9f2e408. Report an issue: GitHub.