nikivdev/code · error · anyhow::Error
codex app-server error: {}
Error message
codex app-server error: {} What it means
The codex app-server answered the request, but the JSON-RPC response contained an "error" object instead of a result. codex_read_response extracts the error's "message" field (defaulting to "unknown codex app-server error") and bails with this message. This is a server-side rejection of the request, not a transport problem.
Source
Thrown at src/skills.rs:1136
bail!("codex app-server response timed out");
}
let line = match lines.next() {
Some(Ok(line)) => line,
Some(Err(err)) => bail!("failed to read from codex app-server: {}", err),
None => bail!("codex app-server closed stdout unexpectedly"),
};
if line.trim().is_empty() {
continue;
}
let msg: serde_json::Value = serde_json::from_str(&line)
.with_context(|| format!("invalid JSON from codex app-server: {}", line))?;
if msg.get("id").and_then(|v| v.as_u64()) == Some(expected_id) {
if let Some(err) = msg.get("error") {
let message = err
.get("message")
.and_then(|v| v.as_str())
.unwrap_or("unknown codex app-server error");
bail!("codex app-server error: {}", message);
}
return Ok(msg);
}
}
}
pub(crate) fn reload_codex_skills_for_cwd(cwd: &Path) -> Result<usize> {
let codex_bin = configured_codex_bin_for_workdir(cwd);
let mut child = Command::new(&codex_bin)
.arg("app-server")
.current_dir(cwd)
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.context("failed to run codex app-server")?;
View on GitHub (pinned to a747e741ae)
Solutions
- Read the embedded server message after 'codex app-server error:' to identify the server-side cause
- Verify the request method/params match the codex app-server protocol version in use
- Ensure the app-server is fully initialized before sending requests
- Upgrade or align the codex binary with the client expectations
Example fix
// before: opaque without context of the request
bail!("codex app-server error: {}", message);
// after: include the request id for correlation
bail!("codex app-server error (id {}): {}", expected_id, message); Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate request params the server is known to reject
assert!(cwd.is_dir(), "cwd passed to app-server must exist: {}", cwd.display()); Try / catch
match codex_read_response(&mut lines, expected_id, deadline) {
Ok(msg) => Ok(msg),
Err(e) if e.to_string().starts_with("codex app-server error:") => {
let server_msg = e.to_string().trim_start_matches("codex app-server error:");
eprintln!("server rejected request: {server_msg}");
// method/param mismatch => fix request, don't retry blindly
Err(e)
}
Err(e) => Err(e),
} Prevention
- Match request method names and params to the app-server protocol version
- Initialize/handshake with the server before other requests
- Log the full JSON-RPC error object, not just the message field
- Keep the codex binary and client in version lockstep
When it happens
Trigger: reload_codex_skills_for_cwd sends a request and the app-server replies with {"id": expected_id, "error": {"message": ...}} — e.g. the requested method is unknown, parameters are invalid, or the server is in a bad state.
Common situations: Protocol version mismatch so the method name is unsupported; invalid request payload (malformed cwd or params); app-server not initialized when the request arrives; permissions or workspace errors on the server side.
Related errors
- codex app-server response timed out
- failed to read from codex: {}
- codex app-server closed stdout unexpectedly
- codex app-server reader disconnected
- codex error: {}
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/ba50e125f3e099ed.
Report an issue: GitHub.