affaan-m/ECC · error
taskkill exited with status
Error message
taskkill exited with status {status} What it means
On Windows, session stop invokes taskkill /PID <pid>; when the command runs but exits non-zero (process already gone, access denied), the status code is wrapped in this error. It reports the raw ExitStatus rather than a friendly reason.
Solutions
- Check the process still exists (tasklist /FI "PID eq <pid>") before taskkill, and treat 'not found' as success
- Run taskkill with /F /T and inspect the exit code; if access denied, elevate or kill from the owning user
- Prefer recording the actual taskkill stderr in the error message for diagnosis
Example fix
// before
Err(anyhow::anyhow!("taskkill exited with status {status}"))
// after
if !status.success() {
anyhow::bail!("taskkill exited with status {status} for process {pid} (process may have already exited)");
} Defensive patterns
Strategy: try-catch
Validate before calling
// Windows: confirm process exists before killing
let out = Command::new("tasklist").args(["/FI", &format!("PID eq {pid}")]).output()?;
if !String::from_utf8_lossy(&out.stdout).contains(&pid.to_string()) {
return Ok(()); // already gone
} Try / catch
match stop_session_windows(pid) {
Ok(()) => (),
Err(e) if e.to_string().contains("taskkill exited") => {
eprintln!("kill failed for {pid}; process may already be gone");
}
Err(e) => return Err(e),
} Prevention
- Treat 'process not found' on kill as success (idempotent stop)
- Run with adequate privileges to terminate child processes
- Use /F /T flags so child trees are killed too
When it happens
Trigger: Calling stop_session on Windows where the target pid no longer exists (already exited), the caller lacks permission to kill it, or taskkill is not on PATH so status reflects invocation failure context.
Common situations: Stopping an already-finished session; stale pid recorded in the DB after a crash; running without sufficient privileges to terminate the child.
Related errors
- agent profile inheritance cycle
- an active harness configuration already exists
- atomic promotion compare-and-swap failed
- atomic rollback compare-and-swap failed
- audit health evidence does not match its evaluation
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/907d7abe3330aeea.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/session/manager.rs:3618
#[cfg(unix)]
fn kill_process(pid: u32) -> Result<()> {
send_signal(pid, libc::SIGTERM)?;
std::thread::sleep(std::time::Duration::from_millis(1200));
send_signal(pid, libc::SIGKILL)?;
Ok(())
}
#[cfg(windows)]
fn kill_process(pid: u32) -> Result<()> {
let status = std::process::Command::new("taskkill")
.args(["/PID", &pid.to_string(), "/T", "/F"])
.status()
.with_context(|| format!("Failed to invoke taskkill for process {pid}"))?;
if status.success() {
Ok(())
} else {
Err(anyhow::anyhow!("taskkill exited with status {status}"))
}
}
#[cfg(unix)]
fn send_signal(pid: u32, signal: i32) -> Result<()> {
let outcome = unsafe { libc::kill(pid as i32, signal) };
if outcome == 0 {
return Ok(());
}
let error = std::io::Error::last_os_error();
if error.raw_os_error() == Some(libc::ESRCH) {
return Ok(());
}
Err(error).with_context(|| format!("Failed to kill process {pid}"))
}
View on GitHub (pinned to 8321021c54)