nikivdev/code · error
kill failed
Error message
kill failed
What it means
This error is thrown by terminate_process when a `kill` command was executed against a PID but the command exited with a non-zero status. It means the OS refused or failed to terminate the target process (the earlier `.context("failed to kill process")` only covers spawn/IO errors). Callers (ensure_server, stop_server) surface it when trying to stop a previously running server instance.
Source
Thrown at src/log_server.rs:298
fn process_alive(pid: u32) -> bool {
Command::new("kill")
.arg("-0")
.arg(pid.to_string())
.status()
.map(|s| s.success())
.unwrap_or(false)
}
fn terminate_process(pid: u32) -> Result<()> {
let status = Command::new("kill")
.arg(pid.to_string())
.status()
.context("failed to kill process")?;
if status.success() {
Ok(())
} else {
bail!("kill failed")
}
}
async fn health() -> impl IntoResponse {
Json(json!({ "status": "ok" }))
}
#[derive(Debug, Deserialize)]
struct CodexSkillsQuery {
path: Option<String>,
limit: Option<usize>,
}
#[derive(Debug, Deserialize)]
struct CodexEvalQuery {
path: Option<String>,
limit: Option<usize>,
}View on GitHub (pinned to a747e741ae)
Solutions
- Check the process with `ps -p <pid>` — if it does not exist, delete the stale PID file and retry.
- Run the stop/ensure command as the same user (or with sudo) that owns the target process.
- Manually kill the process (`kill -9 <pid>`) if it ignores SIGTERM, then clean up the PID file.
- Update the PID file to point at the correct current server PID before calling stop_server again.
Example fix
// before
ensure_server(&pid_path)?; // fails with "kill failed" on stale pid
// after
if let Ok(pid) = std::fs::read_to_string(&pid_path) {
if !process_exists(pid.trim()) {
let _ = std::fs::remove_file(&pid_path); // clear stale pid first
}
}
ensure_server(&pid_path)?; Defensive patterns
Strategy: try-catch
Validate before calling
let pid = std::fs::read_to_string("server.pid")?;
let alive = std::process::Command::new("ps")
.args(["-p", pid.trim()])
.status()
.map(|s| s.success())
.unwrap_or(false);
if !alive { let _ = std::fs::remove_file("server.pid"); } Type guard
fn process_alive(pid: u32) -> bool {
std::process::Command::new("kill").args(["-0", &pid.to_string()]).status().map(|s| s.success()).unwrap_or(false)
} Try / catch
match stop_server(&pid_path) {
Ok(()) => {},
Err(e) if e.to_string() == "kill failed" => {
// stale pid or permission issue: clear pid file, check ownership, retry once
let _ = std::fs::remove_file(&pid_path);
stop_server(&pid_path)?;
}
Err(e) => return Err(e),
} Prevention
- Check the PID exists (kill -0 or ps -p) before attempting to stop it.
- Clean up PID files when the server shuts down normally.
- Run stop/ensure commands as the same user that started the server.
- After reboot, assume PID files are stale and validate before use.
When it happens
Trigger: Calling stop_server or ensure_server when the recorded PID no longer exists (stale PID file), the process is owned by another user (permission denied), or the PID was reused by an unrelated process.
Common situations: A server crashed and left a stale PID file; running under a different user than the one that started the server; PID recycled by the OS after reboot.
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/e05109b8449870d9.
Report an issue: GitHub.