{"record":{"id":"0d286f6b9b4c4390","repo":"openai/codex","slug":"upstream-url-must-include-a-host","errorCode":null,"errorMessage":"upstream URL must include a host","messagePattern":"upstream URL must include a host","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"codex-rs/responses-api-proxy/src/lib.rs","lineNumber":80,"sourceCode":"struct ServerInfo {\n    port: u16,\n    pid: u32,\n}\n\nstruct ForwardConfig {\n    upstream_url: Url,\n    host_header: HeaderValue,\n}\n\n/// Entry point for the library main, for parity with other crates.\npub fn run_main(args: Args) -> Result<()> {\n    let auth_header = read_auth_header_from_stdin()?;\n\n    let upstream_url = Url::parse(&args.upstream_url).context(\"parsing --upstream-url\")?;\n    let host = match (upstream_url.host_str(), upstream_url.port()) {\n        (Some(host), Some(port)) => format!(\"{host}:{port}\"),\n        (Some(host), None) => host.to_string(),\n        _ => return Err(anyhow!(\"upstream URL must include a host\")),\n    };\n    let host_header =\n        HeaderValue::from_str(&host).context(\"constructing Host header from upstream URL\")?;\n\n    let forward_config = Arc::new(ForwardConfig {\n        upstream_url,\n        host_header,\n    });\n    let dump_dir = args\n        .dump_dir\n        .map(ExchangeDumper::new)\n        .transpose()\n        .context(\"creating --dump-dir\")?\n        .map(Arc::new);\n\n    let (listener, bound_addr) = bind_listener(args.port)?;\n    if let Some(path) = args.server_info.as_ref() {\n        write_server_info(path, bound_addr.port())?;","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/responses-api-proxy/src/lib.rs#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Include scheme and host: --upstream-url http://localhost:8080 or --upstream-url https://api.openai.com/v1","Do not use file:/unix:/urn:/mailto: URLs - the proxy only forwards HTTP(S)","To reach a Unix-socket service, front it with an HTTP listener (socat, nginx) and point the proxy at that"],"exampleFix":"# before\ncodex responses-api-proxy --upstream-url localhost:3000\n# after\ncodex responses-api-proxy --upstream-url http://localhost:3000","handlingStrategy":"validation","validationCode":"use url::Url;\n\nfn validate_upstream_url(raw: &str) -> anyhow::Result<()> {\n    let parsed = Url::parse(raw).context(\"parsing --upstream-url\")?;\n    anyhow::ensure!(parsed.host_str().is_some(), \"upstream URL must include a host\");\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match run_main(args).await {\n    Err(e) if e.to_string().contains(\"upstream URL must include a host\") => {\n        eprintln!(\"hint: prefix --upstream-url with http:// or https://\");\n        std::process::exit(2);\n    }\n    other => other,\n}","preventionTips":["Always scheme-prefix URLs in CLI args and config files","Validate the upstream URL at config-load time with url::Url before the proxy starts","Add a URL sanity check in wrapper scripts that spawn the proxy"],"tags":["rust","url-validation","proxy","cli-args"],"backgroundTag":"invalid-url-missing-host","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}