{"record":{"id":"e4d207afde78213b","repo":"chenhg5/cc-connect","slug":"taskkill-failed-w-s","errorCode":null,"errorMessage":"taskkill failed: %w: %s","messagePattern":"taskkill failed: %w: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"agent/claudecode/proc_windows.go","lineNumber":50,"sourceCode":"// signalProcessGroup is a graceful best-effort equivalent of forceKillCmd\n// on Windows: taskkill without /F asks the target to close cleanly. Falls\n// back to cmd.Process.Signal if taskkill is unavailable.\nfunc signalProcessGroup(cmd *exec.Cmd, sig syscall.Signal) error {\n\tif cmd == nil || cmd.Process == nil {\n\t\treturn nil\n\t}\n\tkillCmd := exec.Command(\"taskkill\", \"/T\", \"/PID\", strconv.Itoa(cmd.Process.Pid))\n\toutput, err := killCmd.CombinedOutput()\n\tif err == nil {\n\t\treturn nil\n\t}\n\tif isTaskkillNotRunning(output) {\n\t\treturn nil\n\t}\n\tif killErr := cmd.Process.Signal(sig); killErr == nil || errors.Is(killErr, os.ErrProcessDone) {\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"taskkill failed: %w: %s\", err, processKillOutput(output))\n}\n\n// forceKillCmd taskkill /T /F's the entire descendant tree rooted at cmd.\nfunc forceKillCmd(cmd *exec.Cmd) error {\n\tif cmd == nil || cmd.Process == nil {\n\t\treturn nil\n\t}\n\tkillCmd := exec.Command(\"taskkill\", \"/T\", \"/F\", \"/PID\", strconv.Itoa(cmd.Process.Pid))\n\toutput, err := killCmd.CombinedOutput()\n\tif err == nil {\n\t\treturn nil\n\t}\n\tif isTaskkillNotRunning(output) {\n\t\treturn nil\n\t}\n\tif killErr := cmd.Process.Kill(); killErr == nil || errors.Is(killErr, os.ErrProcessDone) {\n\t\treturn nil\n\t} else {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/claudecode/proc_windows.go#L32-L68","documentation":"signalProcessGroup (agent/claudecode/proc_windows.go:50) stops a Claude Code process tree on Windows by first running 'taskkill /T' to signal the group. If taskkill itself failed (and the failure is not the benign 'no running instance' case), it falls back to cmd.Process.Signal(sig); when that fallback also fails it wraps both as 'taskkill failed: %w: %s' (the taskkill error plus captured output). It indicates the process could not be gracefully signaled.","triggerScenarios":"Calling Stop/signalProcessGroup on Windows where taskkill exits non-zero with output not matching 'there is no running instance', AND cmd.Process.Signal(sig) returns an error other than os.ErrProcessDone.","commonSituations":"Process already exited between the taskkill call and the Signal fallback (most common, benign); insufficient privileges to signal a process owned by another user; taskkill not on PATH or blocked by policy; process in a zombie/uninterruptible state.","solutions":["If the error's second cause is os.ErrProcessDone or 'access is denied' after exit, treat the stop as successful — the process is already gone.","Retry Stop once after a short delay; transient races between exit and signal are common.","Check captured taskkill output (the %s part) for 'access is denied' and run cc-connect with sufficient privileges or as the process owner.","Verify taskkill.exe is available (it is a standard Windows binary); if removed by hardening policies, use the Unix-style build or a fallback kill path."],"exampleFix":"// before\nerr := session.Stop(ctx)\nif err != nil { log.Error(err) }\n// after\nerr := session.Stop(ctx)\nif err != nil {\n    var pe *os.ProcessState // or check message\n    if errors.Is(err, os.ErrProcessDone) || strings.Contains(err.Error(), \"No results\") {\n        log.Info(\"process already exited; stop treated as success\")\n        return nil\n    }\n    log.Error(err)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := session.Stop(ctx); err != nil {\n    if errors.Is(err, os.ErrProcessDone) || strings.Contains(err.Error(), \"already\") {\n        return nil // already exited; benign\n    }\n    time.Sleep(500 * time.Millisecond)\n    if err2 := session.Stop(ctx); err2 != nil {\n        log.Warn(\"stop failed; process may linger\", \"err\", err2)\n    }\n}","preventionTips":["Treat os.ErrProcessDone and 'no running instance' outputs as success.","Retry Stop once after a short delay to absorb exit/signal races.","Run cc-connect with privileges to signal the spawned process tree.","Log the captured taskkill output (%s) for diagnosis."],"tags":["windows","process-management","taskkill"],"backgroundTag":"command-not-found","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}