BigPizzaV3/CodexPlusPlus · error
无法启动 Codex app-server(
Error message
无法启动 Codex app-server({executable}){hint}({error}) What it means
Thrown when spawning the Codex app-server child process fails. The library wraps std::process::Command spawn errors and appends a hint depending on the io::ErrorKind: NotFound means the executable path does not exist (or is not on PATH), PermissionDenied means the file is not executable. The underlying OS error is preserved in {error}.
Solutions
- Set the full absolute path to the Codex CLI executable in settings (e.g. /usr/local/bin/codex or ~/.cargo/bin/codex)
- Verify the binary exists and is executable: ls -l $(which codex) / chmod +x
- Ensure PATH includes the install dir when launching from a GUI app (GUI apps inherit launchd PATH, not shell PATH)
- Reinstall or update the Codex CLI if the binary is missing after an upgrade
Example fix
// before (settings) codexPath: "codex" // after codexPath: "/usr/local/bin/codex"
Defensive patterns
Strategy: try-catch
Validate before calling
let p = settings.codex_path.clone();
if p.is_empty() || !std::path::Path::new(&p).exists() {
return Err(format!("Codex CLI not found at '{p}'; set the full executable path"));
}
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mode = std::fs::metadata(&p)?.permissions().mode();
if mode & 0o111 == 0 { return Err("Codex CLI is not executable".into()); }
} Type guard
fn is_executable_file(path: &str) -> bool {
let p = std::path::Path::new(path);
p.is_file() && std::fs::metadata(p)
.map(|m| !m.permissions().readonly())
.unwrap_or(false)
} Try / catch
match app_server::start(config).await {
Err(e) if e.to_string().contains("无法启动 Codex app-server") => {
eprintln!("Check the codex executable path and permissions: {e}");
}
Err(e) => return Err(e),
Ok(v) => v,
} Prevention
- Always store an absolute path to the Codex CLI in settings
- After upgrading or reinstalling codex, re-verify the configured path
- On GUI apps remember PATH differs from your shell; use absolute paths
- Keep the binary executable (chmod +x) and out of quarantined locations
When it happens
Trigger: Calling start (via start_helper_waiting_for_busy_port) with a configured Codex CLI path that does not exist, is not on PATH, or lacks the execute bit; also any other spawn failure (e.g. resource limits, E2BIG).
Common situations: User left the codex executable path empty or mistyped after upgrading; codex installed via npm/cargo not on the GUI app's PATH; binary downloaded without +x; antivirus or sandbox blocking exec.
Related errors
- 无法启动 :
- 启动静默入口失败: ;回滚 live 配置也失败:
- throw new Error( );
- archived lookup task failed
- built-in Dream Skin theme cannot be deleted
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/b081810c4cd7c3a0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/connect/app_server.rs:118
};
validate_codex_executable(executable)?;
let mut command = Command::new(executable);
command
.arg("app-server")
.current_dir(&config.work_dir)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.kill_on_drop(true);
let mut child = command.spawn().map_err(|error| {
let hint = match error.kind() {
std::io::ErrorKind::NotFound => {
":找不到该文件;填 Codex CLI 可执行文件的完整路径,或确保 codex 在 PATH 里"
}
std::io::ErrorKind::PermissionDenied => ":没有执行权限",
_ => "",
};
anyhow::anyhow!("无法启动 Codex app-server({executable}){hint}({error})")
})?;
let stdin = child
.stdin
.take()
.context("无法连接 Codex app-server stdin")?;
let stdout = child
.stdout
.take()
.context("无法连接 Codex app-server stdout")?;
// 别把 stderr 读了就扔——app-server 起不来时,真正的原因只在这里。
// 留最近几行,初始化失败时附到错误信息上。
let stderr_tail = Arc::new(Mutex::new(VecDeque::<String>::new()));
if let Some(stderr) = child.stderr.take() {
let sink = Arc::clone(&stderr_tail);
tokio::spawn(async move {
let mut lines = BufReader::new(stderr).lines();
while let Ok(Some(line)) = lines.next_line().await {
let line = line.trim().to_string();View on GitHub (pinned to b1ed92e5e4)