BigPizzaV3/CodexPlusPlus · error · anyhow::Error

Codex app-server 已关闭{}

Error message

Codex app-server 已关闭{}

What it means

read_message got EOF on the app-server stdout: the child process is gone. The library marks the server not running and appends the child exit status, when it can still be reaped, to the message. Every pending run_turn or request call fails with this error once the process dies.

Source

Thrown at crates/codex-plus-core/src/connect/app_server.rs:300

            if response_id(&message) != Some(id) {
                continue;
            }
            if let Some(error) = rpc_error(&message) {
                bail!("Codex app-server {method} 失败:{error}");
            }
            return Ok(message.get("result").cloned().unwrap_or(Value::Null));
        }
    }

    async fn read_message(&mut self, timeout: Duration) -> anyhow::Result<Value> {
        loop {
            let line = tokio::time::timeout(timeout, self.stdout.next_line())
                .await
                .context("等待 Codex app-server 响应超时")??;
            let Some(line) = line else {
                self.running = false;
                let exit = self.child.try_wait().ok().flatten();
                bail!(
                    "Codex app-server 已关闭{}",
                    exit.map(|status| format!(":{status}")).unwrap_or_default()
                );
            };
            let line = line.trim();
            if line.is_empty() {
                continue;
            }
            match serde_json::from_str(line) {
                Ok(message) => return Ok(message),
                Err(_) => continue,
            }
        }
    }

    async fn reject_server_request(&mut self, message: &Value) -> anyhow::Result<()> {
        let Some(id) = message.get("id") else {
            return Ok(());

View on GitHub (pinned to f2074595a2)

Solutions

  1. Run the configured app-server command by hand and watch why it exits
  2. Fix config.codex_path or install codex so the binary resolves on PATH
  3. Complete codex login once interactively
  4. The connector drops the server and restarts on the next message, after fixing the cause send another message to confirm
Defensive patterns

Strategy: retry

Validate before calling

let exe = std::path::Path::new(&config.executable);
if !exe.is_file() { bail!("codex executable missing: {}", exe.display()); }
// optional: run exe with --version once to prove it starts

Try / catch

match server.run_turn(&thread_id, prompt).await {
    Ok(r) => r,
    Err(e) if e.to_string().contains("已关闭") => {
        let mut fresh = CodexAppServer::start(config.clone()).await?;
        fresh.run_turn(&thread_id, prompt).await?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: The codex app-server crashed or exited: config.codex_path points at a binary that is not an app-server and exits immediately, codex is missing on PATH, the CLI is not logged in and exits, an OOM kill, or a manual kill.

Common situations: codex_path misconfigured in the profile; codex CLI updated and the old path removed; first run without login; system OOM during a big turn.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@f2074595a2 (2026-08-23). Data as JSON: /api/errors/643c20a8bb24a6bc. Report an issue: GitHub.