openai/codex · error · anyhow::Error

creating HTTP server: {err}

Error message

creating HTTP server: {err}

What it means

After bind_listener succeeds, run_main wraps the listener with Server::from_listener. If constructing the server from the listener fails (socket option setup, internal task spawn), the error is wrapped as 'creating HTTP server: {err}' with the underlying cause carried in the message suffix.

Source

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

        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())?;
    }
    let server = Server::from_listener(listener, None)
        .map_err(|err| anyhow!("creating HTTP server: {err}"))?;
    let client = Arc::new(
        Client::builder()
            // Disable reqwest's 30s default so long-lived response streams keep flowing.
            .timeout(None::<Duration>)
            .build()
            .context("building reqwest client")?,
    );

    eprintln!("responses-api-proxy listening on {bound_addr}");

    let http_shutdown = args.http_shutdown;
    for request in server.incoming_requests() {
        let client = client.clone();
        let forward_config = forward_config.clone();
        let dump_dir = dump_dir.clone();
        std::thread::spawn(move || {
            if http_shutdown && request.method() == &Method::Get && request.url() == "/shutdown" {
                let _ = request.respond(Response::new_empty(StatusCode(200)));

View on GitHub (pinned to 339751715c)

Solutions

  1. Read the text after 'creating HTTP server:' - it contains the real io/runtime error
  2. Check and raise file-descriptor limits (ulimit -n) if the process is near exhaustion
  3. Restart the proxy; transient setup failures usually clear on retry
  4. If reproducible, capture full stderr and report upstream with the wrapped cause
Defensive patterns

Strategy: try-catch

Try / catch

match run_main(args).await {
    Ok(()) => {}
    Err(e) if e.to_string().starts_with("creating HTTP server") => {
        eprintln!("proxy failed to initialize server: {e:#}");
        std::process::exit(1);
    }
    Err(e) => { eprintln!("proxy error: {e:#}"); std::process::exit(1); }
}

Prevention

When it happens

Trigger: Server::from_listener returning Err right after a successful bind - for example failure configuring the accepted socket, a runtime/task spawn failure, or a listener handle in an invalid state.

Common situations: File-descriptor exhaustion (EMFILE) around accept-loop setup; restricted sandboxes blocking socket option calls; rare fork/exec edge cases. The common startup failure 'failed to bind {addr}' happens earlier and is a different error.

Related errors


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