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

  1. Treat 'Process not found' as success - the goal (process gone) is already achieved
  2. Await or observe child.status before killing, and skip kill when exit is already known
  3. 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

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


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/b91df9c9b786eae6. Report an issue: GitHub.