{"record":{"id":"e343b431c4489c71","repo":"openai/codex","slug":"server-stopped-unexpectedly","errorCode":null,"errorMessage":"server stopped unexpectedly","messagePattern":"server stopped unexpectedly","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"codex-rs/responses-api-proxy/src/lib.rs","lineNumber":135,"sourceCode":"        std::thread::spawn(move || {\n            if http_shutdown && request.method() == &Method::Get && request.url() == \"/shutdown\" {\n                let _ = request.respond(Response::new_empty(StatusCode(200)));\n                std::process::exit(0);\n            }\n\n            if let Err(e) = forward_request(\n                &client,\n                auth_header,\n                &forward_config,\n                dump_dir.as_deref(),\n                request,\n            ) {\n                eprintln!(\"forwarding error: {e}\");\n            }\n        });\n    }\n\n    Err(anyhow!(\"server stopped unexpectedly\"))\n}\n\nfn bind_listener(port: Option<u16>) -> Result<(TcpListener, SocketAddr)> {\n    let addr = SocketAddr::from(([127, 0, 0, 1], port.unwrap_or(0)));\n    let listener = TcpListener::bind(addr).with_context(|| format!(\"failed to bind {addr}\"))?;\n    let bound = listener.local_addr().context(\"failed to read local_addr\")?;\n    Ok((listener, bound))\n}\n\nfn write_server_info(path: &Path, port: u16) -> Result<()> {\n    if let Some(parent) = path.parent()\n        && !parent.as_os_str().is_empty()\n    {\n        fs::create_dir_all(parent)?;\n    }\n\n    let info = ServerInfo {\n        port,","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/responses-api-proxy/src/lib.rs#L117-L153","documentation":"run_main's happy path never returns normally - it awaits the HTTP server. If the server future completes without an intentional shutdown, control falls through to Err(anyhow!(\"server stopped unexpectedly\")) as a sentinel: the accept/serve loop ended on its own, and the actual cause is normally logged just above it (for example 'forwarding error: ...' lines).","triggerScenarios":"The bound listener closes or the serve loop exits at runtime: a fatal accept error, the listener closed externally, or the server task terminating while run_main is still waiting on shutdown signals.","commonSituations":"Container orchestrators or supervisors closing sockets; running the proxy under a timeout wrapper that tears down the listener; internal errors aborting the serve loop; tests dropping the server handle.","solutions":["Read stderr above this error - the root cause (accept or forwarding error) is printed there","Check whether something killed the process or its socket (OOM killer, orchestrator stop, timeout wrapper)","Restart the proxy under a supervisor with backoff","If it recurs with clean logs, capture stderr and file an upstream issue - intentional shutdown returns Ok, not this error"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match run_main(args).await {\n    Err(e) if e.to_string() == \"server stopped unexpectedly\" => {\n        // fatal but restartable: re-launch with backoff under a supervisor\n        supervisor_restart_with_backoff();\n    }\n    other => other,\n}","preventionTips":["Run under systemd/supervisord with Restart=on-failure","Keep stderr logging enabled - the real cause prints before this sentinel error","Avoid external tools that close or manipulate the proxy's listener socket"],"tags":["rust","http-server","runtime-failure","networking"],"backgroundTag":"server-terminated-unexpectedly","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}