denoland/deno · warning
Process not found
Error message
Process not found
What it means
ChildProcess::kill() sends the termination request through the libuv-style backend and maps a UV_ESRCH status to ErrorKind::InvalidInput with the message 'Process not found'. ESRCH means the target PID no longer exists, so on this Windows codepath the child had already exited and been reaped before kill() ran.
Source
Thrown at runtime/subprocess_windows/src/process.rs:419
} else {
Ok(())
}
}
#[derive(Debug)]
pub struct ChildProcess {
pid: i32,
handle: OwnedHandle,
waiting: Option<Waiting>,
}
impl crate::Kill for ChildProcess {
fn kill(&mut self) -> std::io::Result<()> {
process_kill(self.pid, SIGTERM).map_err(|e| {
if let Some(sys_error) = e.as_sys_error() {
std::io::Error::from_raw_os_error(sys_error as i32)
} else if e.as_uv_error() == uv_error::UV_ESRCH {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Process not found",
)
} else {
std::io::Error::other(format!(
"Failed to kill process: {}",
e.as_uv_error()
))
}
})
}
}
impl ChildProcess {
pub fn pid(&self) -> i32 {
self.pid
}
pub fn try_wait(&mut self) -> Result<Option<i32>, std::io::Error> {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Treat 'Process not found' as success - the goal (process gone) is already achieved
- Await or observe child.status before killing, and skip kill when exit is already known
- Route all kills through an idempotent helper that swallows this specific error
Example fix
// before
child.kill(); // throws "Process not found" if it already exited
// after
function safeKill(child: Deno.Child) {
try {
child.kill();
} catch {
// already exited - nothing to signal
}
} Defensive patterns
Strategy: try-catch
Validate before calling
let exited = false; child.status.then(() => (exited = true)); // later, in cleanup: if (!exited) child.kill();
Try / catch
try {
child.kill();
} catch (err) {
if (err instanceof Error && /Process not found/.test(err.message)) return; // idempotent kill
throw err;
} Prevention
- Make kill idempotent: swallow 'Process not found' since the objective (process gone) is met
- Await child.status before attempting cleanup kills
- Track child exit state with a flag set from the status promise
When it happens
Trigger: Calling child.kill() on a Deno.Command child that has already exited: killing twice, killing after awaiting child.status, or a timeout/cleanup handler whose kill races with the child's natural exit.
Common situations: Timeout wrappers that try to kill a process which finished first; cleanup handlers (SIGINT handlers, finally blocks) that kill again after an earlier kill; children that crash while the parent is preparing to terminate them.
Related errors
- Child process has already terminated
- {}: ({}) {}
- failed to unregister: {}
- nul byte found in provided data
- Invalid arguments
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/b91df9c9b786eae6.
Report an issue: GitHub.