{"record":{"id":"b91df9c9b786eae6","repo":"denoland/deno","slug":"process-not-found","errorCode":null,"errorMessage":"Process not found","messagePattern":"Process not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"runtime/subprocess_windows/src/process.rs","lineNumber":419,"sourceCode":"  } else {\n    Ok(())\n  }\n}\n\n#[derive(Debug)]\npub struct ChildProcess {\n  pid: i32,\n  handle: OwnedHandle,\n  waiting: Option<Waiting>,\n}\n\nimpl crate::Kill for ChildProcess {\n  fn kill(&mut self) -> std::io::Result<()> {\n    process_kill(self.pid, SIGTERM).map_err(|e| {\n      if let Some(sys_error) = e.as_sys_error() {\n        std::io::Error::from_raw_os_error(sys_error as i32)\n      } else if e.as_uv_error() == uv_error::UV_ESRCH {\n        std::io::Error::new(\n          std::io::ErrorKind::InvalidInput,\n          \"Process not found\",\n        )\n      } else {\n        std::io::Error::other(format!(\n          \"Failed to kill process: {}\",\n          e.as_uv_error()\n        ))\n      }\n    })\n  }\n}\n\nimpl ChildProcess {\n  pub fn pid(&self) -> i32 {\n    self.pid\n  }\n  pub fn try_wait(&mut self) -> Result<Option<i32>, std::io::Error> {","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/runtime/subprocess_windows/src/process.rs#L401-L437","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nchild.kill(); // throws \"Process not found\" if it already exited\n\n// after\nfunction safeKill(child: Deno.Child) {\n  try {\n    child.kill();\n  } catch {\n    // already exited - nothing to signal\n  }\n}","handlingStrategy":"try-catch","validationCode":"let exited = false;\nchild.status.then(() => (exited = true));\n// later, in cleanup:\nif (!exited) child.kill();","typeGuard":null,"tryCatchPattern":"try {\n  child.kill();\n} catch (err) {\n  if (err instanceof Error && /Process not found/.test(err.message)) return; // idempotent kill\n  throw err;\n}","preventionTips":["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"],"tags":["windows","subprocess","kill","race-condition"],"backgroundTag":"process-already-exited","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}