{"record":{"id":"79bb8aff2a0b58b8","repo":"google/zx","slug":"too-late-to-kill-the-process","errorCode":null,"errorMessage":"Too late to kill the process.","messagePattern":"Too late to kill the process\\.","errorType":"exception","errorClass":"Fail","httpStatus":null,"severity":"error","filePath":"src/core.ts","lineNumber":447,"sourceCode":"        throw output.cause || output\n      }\n      this._reject(output)\n      if (this.sync) throw output\n    }\n  }\n\n  abort(reason?: string) {\n    if (this.isSettled()) throw new Fail('Too late to abort the process.')\n    if (this.signal !== this.ac.signal)\n      throw new Fail('The signal is controlled by another process.')\n    if (!this.child)\n      throw new Fail('Trying to abort a process without creating one.')\n\n    this.ac.abort(reason)\n  }\n\n  kill(signal?: NodeJS.Signals | null): Promise<void> {\n    if (this.isSettled()) throw new Fail('Too late to kill the process.')\n    if (!this.child)\n      throw new Fail('Trying to kill a process without creating one.')\n    if (!this.pid) throw new Fail('The process pid is undefined.')\n\n    return $.kill(this.pid, signal || this._snapshot.killSignal || $.killSignal)\n  }\n\n  // Configurators\n  stdio(\n    stdin: IOType | StdioOptions,\n    stdout: IOType = 'pipe',\n    stderr: IOType = 'pipe'\n  ): this {\n    this._snapshot.stdio = Array.isArray(stdin)\n      ? stdin\n      : [stdin, stdout, stderr]\n    return this\n  }","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/google/zx/blob/00a2c484e219c2e84bfc3a199febf7fbce2cfbf4/src/core.ts#L429-L465","documentation":"Thrown by ProcessPromise.kill() when the process has already settled. There is no live child to send a signal to after exit, so zx refuses rather than emit a spurious ESRCH.","triggerScenarios":"Calling `pp.kill()` inside `.finally()`/`.then()`; after `await pp`; in a post-completion cleanup routine; a timeout-kill watchdog losing the race against a fast command.","commonSituations":"Cleanup that always attempts to kill; timeout logic racing fast commands; reusing kill handlers across commands.","solutions":["Guard the call: `if (!pp.isSettled()) pp.kill()`.","Use $.timeout / pp.timeout() for bounded, race-safe kills.","Move the kill before the await expression."],"exampleFix":"// before\nawait pp\npp.kill()\n// after\nif (!pp.isSettled()) pp.kill()","handlingStrategy":"validation","validationCode":"let settled = false\npp.finally(() => { settled = true })\n\nfunction safeKill(p: ProcessPromise): void {\n  if (!settled) p.kill()\n}","typeGuard":null,"tryCatchPattern":"try {\n  pp.kill()\n} catch (e) {\n  if (e instanceof Fail && /Too late to kill/.test(e.message)) {\n    // already exited — no-op\n  } else throw e\n}","preventionTips":["Guard every kill() with an isSettled()/stage check.","Use $.timeout for race-safe bounded kills instead of manual cleanup.","Avoid kill() in finally blocks unless gated on stage."],"tags":["kill","lifecycle","signal"],"backgroundTag":null,"analyzedSha":"00a2c484e219c2e84bfc3a199febf7fbce2cfbf4","analyzedAt":"2026-08-13T02:11:06.305Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}