openai/codex · error

upstream URL must include a host

Error message

upstream URL must include a host

What it means

run_main parses --upstream-url with Url::parse (malformed or relative input already fails earlier as 'parsing --upstream-url') and then builds the Host header used for forwarding. If the URL parses but has no authority component (host_str() is None), no Host header can be constructed, so it fails immediately with this anyhow error.

Source

Thrown at codex-rs/responses-api-proxy/src/lib.rs:80

struct ServerInfo {
    port: u16,
    pid: u32,
}

struct ForwardConfig {
    upstream_url: Url,
    host_header: HeaderValue,
}

/// Entry point for the library main, for parity with other crates.
pub fn run_main(args: Args) -> Result<()> {
    let auth_header = read_auth_header_from_stdin()?;

    let upstream_url = Url::parse(&args.upstream_url).context("parsing --upstream-url")?;
    let host = match (upstream_url.host_str(), upstream_url.port()) {
        (Some(host), Some(port)) => format!("{host}:{port}"),
        (Some(host), None) => host.to_string(),
        _ => return Err(anyhow!("upstream URL must include a host")),
    };
    let host_header =
        HeaderValue::from_str(&host).context("constructing Host header from upstream URL")?;

    let forward_config = Arc::new(ForwardConfig {
        upstream_url,
        host_header,
    });
    let dump_dir = args
        .dump_dir
        .map(ExchangeDumper::new)
        .transpose()
        .context("creating --dump-dir")?
        .map(Arc::new);

    let (listener, bound_addr) = bind_listener(args.port)?;
    if let Some(path) = args.server_info.as_ref() {
        write_server_info(path, bound_addr.port())?;

View on GitHub (pinned to 339751715c)

Solutions

  1. Include scheme and host: --upstream-url http://localhost:8080 or --upstream-url https://api.openai.com/v1
  2. Do not use file:/unix:/urn:/mailto: URLs - the proxy only forwards HTTP(S)
  3. To reach a Unix-socket service, front it with an HTTP listener (socat, nginx) and point the proxy at that

Example fix

# before
codex responses-api-proxy --upstream-url localhost:3000
# after
codex responses-api-proxy --upstream-url http://localhost:3000
Defensive patterns

Strategy: validation

Validate before calling

use url::Url;

fn validate_upstream_url(raw: &str) -> anyhow::Result<()> {
    let parsed = Url::parse(raw).context("parsing --upstream-url")?;
    anyhow::ensure!(parsed.host_str().is_some(), "upstream URL must include a host");
    Ok(())
}

Try / catch

match run_main(args).await {
    Err(e) if e.to_string().contains("upstream URL must include a host") => {
        eprintln!("hint: prefix --upstream-url with http:// or https://");
        std::process::exit(2);
    }
    other => other,
}

Prevention

When it happens

Trigger: Passing --upstream-url localhost:8080 (parses as scheme 'localhost' with no host - the classic missing http:// prefix), file:///var/run/app.sock, unix:/tmp/sock, mailto: or urn: URLs, or http:///path with an empty authority.

Common situations: Forgetting the http:// or https:// scheme prefix; trying to point the proxy at a Unix socket or file path; copy-pasting a bare host:port string from documentation.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/0d286f6b9b4c4390. Report an issue: GitHub.