chenhg5/cc-connect · error
taskkill failed: %w: %s; process kill fallback failed: %w
Error message
taskkill failed: %w: %s; process kill fallback failed: %w
What it means
On Windows, forceKillCmd first tries `taskkill /F /T`; if that fails (and the failure is not 'process not found'), it falls back to cmd.Process.Kill(). If BOTH the taskkill invocation and the direct process-kill fallback fail, it wraps both errors into this combined error. It means the codex subprocess could not be terminated.
Source
Thrown at agent/codex/proc_windows.go:44
func forceKillCmd(cmd *exec.Cmd) error {
if cmd == nil || cmd.Process == nil {
return nil
}
killCmd := exec.Command("taskkill", "/T", "/F", "/PID", strconv.Itoa(cmd.Process.Pid))
output, err := killCmd.CombinedOutput()
if err == nil {
return nil
}
if bytes.Contains(bytes.ToLower(output), []byte("there is no running instance")) {
return nil
}
if bytes.Contains(bytes.ToLower(output), []byte("not found")) {
return nil
}
if killErr := cmd.Process.Kill(); killErr == nil || errors.Is(killErr, os.ErrProcessDone) {
return nil
} else {
return fmt.Errorf("taskkill failed: %w: %s; process kill fallback failed: %w", err, processKillOutput(output), killErr)
}
}
func processKillOutput(output []byte) string {
trimmed := strings.TrimSpace(string(output))
if trimmed == "" {
return "(empty output)"
}
return trimmed
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Re-run the stop operation — if the process exited concurrently this is transient.
- Run cc-connect with sufficient privileges on Windows to force-kill child processes.
- Check the embedded taskkill output (first %w/%s) for the OS reason (e.g. Access Denied) and address it.
- Verify the codex process is not protected by security software or an elevated context.
Example fix
// before
err := agent.Stop() // combined taskkill+kill failure, process may linger
// after
err := agent.Stop()
if err != nil && strings.Contains(err.Error(), "taskkill failed") {
log.Printf("codex kill failed, verifying PID alive: %v", err)
// check process liveness before retrying or reporting
} Defensive patterns
Strategy: retry
Validate before calling
// Windows: verify we can signal the process before stopping
if err := p.Signal(syscall.Signal(0)); err != nil {
return nil // already gone; no kill needed
} Try / catch
err := agent.Stop()
if err != nil && strings.Contains(err.Error(), "taskkill failed") {
log.Warn("codex kill failed; checking liveness", "err", err)
if alive(pid) { time.Sleep(500 * time.Millisecond); err = agent.Stop() }
} Prevention
- Run cc-connect on Windows with privileges sufficient to terminate child process trees.
- Exclude the codex process from AV/EDR process-protection rules.
- Verify process liveness after a failed kill instead of assuming it survived.
- Log the embedded taskkill output to diagnose Access Denied quickly.
When it happens
Trigger: Windows builds only: taskkill returns a non-'not found' error AND cmd.Process.Kill() fails with something other than os.ErrProcessDone — e.g. insufficient privileges, process already exited in a way Kill reports, or access denied to the child tree.
Common situations: Killing a process owned by another user/elevated session; antivirus or job-object policies blocking termination; the process exiting concurrently between the two attempts; running without the privileges taskkill /F requires.
Related errors
- taskkill failed: %w: %s
- taskkill failed: %w: %s; process kill fallback failed: %w
- sudo is not supported on Windows
- run_as_user is not supported on Windows
- taskkill failed: %w: %s; process kill fallback failed: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/420288ca101f581b.
Report an issue: GitHub.