google/zx · error · Fail

Too late to kill the process.

Error message

Too late to kill the process.

What it means

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.

Source

Thrown at src/core.ts:447

        throw output.cause || output
      }
      this._reject(output)
      if (this.sync) throw output
    }
  }

  abort(reason?: string) {
    if (this.isSettled()) throw new Fail('Too late to abort the process.')
    if (this.signal !== this.ac.signal)
      throw new Fail('The signal is controlled by another process.')
    if (!this.child)
      throw new Fail('Trying to abort a process without creating one.')

    this.ac.abort(reason)
  }

  kill(signal?: NodeJS.Signals | null): Promise<void> {
    if (this.isSettled()) throw new Fail('Too late to kill the process.')
    if (!this.child)
      throw new Fail('Trying to kill a process without creating one.')
    if (!this.pid) throw new Fail('The process pid is undefined.')

    return $.kill(this.pid, signal || this._snapshot.killSignal || $.killSignal)
  }

  // Configurators
  stdio(
    stdin: IOType | StdioOptions,
    stdout: IOType = 'pipe',
    stderr: IOType = 'pipe'
  ): this {
    this._snapshot.stdio = Array.isArray(stdin)
      ? stdin
      : [stdin, stdout, stderr]
    return this
  }

View on GitHub (pinned to 00a2c484e2)

Solutions

  1. Guard the call: `if (!pp.isSettled()) pp.kill()`.
  2. Use $.timeout / pp.timeout() for bounded, race-safe kills.
  3. Move the kill before the await expression.

Example fix

// before
await pp
pp.kill()
// after
if (!pp.isSettled()) pp.kill()
Defensive patterns

Strategy: validation

Validate before calling

let settled = false
pp.finally(() => { settled = true })

function safeKill(p: ProcessPromise): void {
  if (!settled) p.kill()
}

Try / catch

try {
  pp.kill()
} catch (e) {
  if (e instanceof Fail && /Too late to kill/.test(e.message)) {
    // already exited — no-op
  } else throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: Cleanup that always attempts to kill; timeout logic racing fast commands; reusing kill handlers across commands.

Related errors


AI-assisted analysis of google/zx@00a2c484e2 (2026-08-13). Data as JSON: /api/errors/79bb8aff2a0b58b8. Report an issue: GitHub.