codex - 💡(How to fix) Fix codex-companion cancel fails on Windows + Git Bash due to MSYS path conversion

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

Error: Shell command failed for pattern "!node "C:/Users/Lenovo/.claude/plugins/cache/openai-codex/codex/1.0.4/scripts/codex-companion.mjs" cancel "task-mp9b4g4b-rt35lr"": [stderr] (node:8320) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities, as the arguments are not escaped, only concatenated. (Use node --trace-deprecation ... to show where the warning was created) taskkill /PID 43280 /T /F: exit=1: 错误: 无效参数/选项 - 'C:/Program Files/Git/PID'。 请键入 "TASKKILL /?" 以了解用法。

Root Cause

On Windows with Git Bash (MSYS) as the default shell, /codex:cancel <task-id> consistently fails because the taskkill /PID <pid> /T /F invocation gets corrupted by MSYS path conversion — /PID is mangled into C:/Program Files/Git/PID and passed to taskkill as an invalid argument. The zombie task is never killed, the worker stays alive, the task slot is never released, and the user is permanently locked out of running new codex tasks until they manually taskkill from a real cmd.exe.

Fix Action

Fix / Workaround

Workaround for affected users (until fixed)

Code Example

node ".../codex-companion.mjs" cancel "task-mp9b4g4b-rt35lr"

---

taskkill /PID 43280 /T /F

---

taskkill "C:/Program Files/Git/PID" 43280 /T /F

---

Error: Shell command failed for pattern "!`node "C:/Users/Lenovo/.claude/plugins/cache/openai-codex/codex/1.0.4/scripts/codex-companion.mjs" cancel "task-mp9b4g4b-rt35lr"`": [stderr]
(node:8320) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities, as the arguments are not escaped, only concatenated.
(Use `node --trace-deprecation ...` to show where the warning was created)
taskkill /PID 43280 /T /F: exit=1: 错误: 无效参数/选项 - 'C:/Program Files/Git/PID'请键入 "TASKKILL /?" 以了解用法。

---

const child = spawn(process.execPath, [scriptPath, "task-worker", "--cwd", cwd, "--job-id", jobId], {
  ...
});

---

// Instead of:
spawn("taskkill", ["/PID", pid, "/T", "/F"], { shell: true });

// Use:
spawn("taskkill", ["/PID", String(pid), "/T", "/F"], { shell: false });

---

spawn("taskkill", ["//PID", String(pid), "//T", "//F"], {
  shell: true,
  env: { ...process.env, MSYS_NO_PATHCONV: "1" }
});

---

const shell = process.platform === "win32" ? "cmd.exe" : "/bin/sh";
spawn(shell, ["/c", `taskkill /PID ${pid} /T /F`], { shell: false });

---

tasklist | findstr node

---

taskkill /PID <pid> /T /F

---

rmdir /S /Q "<repo>\.claude\worktrees\<task-name>"

---

// Should pass on Windows when run from a Git Bash environment
test("cancel kills worker via taskkill without path conversion", () => {
  // Simulate Git Bash env: process.env.MSYSTEM = "MINGW64"
  // Spawn worker, then cancel
  // Assert: worker process exits, no "Invalid argument" stderr
});
RAW_BUFFERClick to expand / collapse

TL;DR

On Windows with Git Bash (MSYS) as the default shell, /codex:cancel <task-id> consistently fails because the taskkill /PID <pid> /T /F invocation gets corrupted by MSYS path conversion — /PID is mangled into C:/Program Files/Git/PID and passed to taskkill as an invalid argument. The zombie task is never killed, the worker stays alive, the task slot is never released, and the user is permanently locked out of running new codex tasks until they manually taskkill from a real cmd.exe.

In our case one zombie task (task-mp9b4g4b-rt35lr) blocked all subsequent codex-rescue work for over 1 hour with no recovery path.

Environment

OSWindows 10/11 (MINGW64_NT-10.0-26200) — Chinese locale
codex-cli0.128.0
codex-companion pluginopenai-codex/codex/1.0.4 (under Claude Code plugin cache)
ShellGit Bash GNU bash 5.2.37(1)-release (x86_64-pc-msys)
Node(whatever Claude Code ships) — emits DEP0190 warning about shell:true
Claude Codewith codex:codex-rescue agent integration

Steps to Reproduce

  1. From Claude Code, invoke the codex:codex-rescue agent with a long-running task that uses npm run build or any other Windows subprocess output capture.

  2. The agent may hang on reading stdout from that subprocess (a separate bug — first observed in a session where codex was implementing a multi-file refactor and froze at npm run build output read). The companion reports the task as running but no progress is made for 30+ minutes.

  3. User runs /codex:cancel <task-id> from Claude Code.

  4. Behind the scenes, the companion runs:

    node ".../codex-companion.mjs" cancel "task-mp9b4g4b-rt35lr"
  5. The companion attempts to kill the worker process via process.kill(pid) (Node-internal taskkill on Windows), which spawns:

    taskkill /PID 43280 /T /F
  6. Bug: When spawned with shell: true under Git Bash, MSYS converts the /PID argument to C:/Program Files/Git/PID, so the actual invocation becomes:

    taskkill "C:/Program Files/Git/PID" 43280 /T /F
  7. taskkill exits with code 1. The stderr message (Chinese Windows locale) is: 错误: 无效参数/选项 - 'C:/Program Files/Git/PID'。请键入 "TASKKILL /?" 以了解用法。 — English equivalent: ERROR: Invalid argument/option - 'C:/Program Files/Git/PID'. Type "TASKKILL /?" for usage.

Actual error output (verbatim)

Error: Shell command failed for pattern "!`node "C:/Users/Lenovo/.claude/plugins/cache/openai-codex/codex/1.0.4/scripts/codex-companion.mjs" cancel "task-mp9b4g4b-rt35lr"`": [stderr]
(node:8320) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead to security vulnerabilities, as the arguments are not escaped, only concatenated.
(Use `node --trace-deprecation ...` to show where the warning was created)
taskkill /PID 43280 /T /F: exit=1: 错误: 无效参数/选项 - 'C:/Program Files/Git/PID'。
请键入 "TASKKILL /?" 以了解用法。

(The Chinese lines translate to: ERROR: Invalid argument/option - 'C:/Program Files/Git/PID'. Type "TASKKILL /?" for usage.)

The DEP0190 warning is itself a smoking gun: the companion is using child_process.spawn with shell: true, which on MSYS triggers the path conversion.

Expected behavior

  • taskkill actually kills PID 43280 and its child processes.
  • Task task-mp9b4g4b-rt35lr transitions to cancelled state.
  • Worktree .claude/worktrees/<task-name> is cleaned up.
  • Task slot is released; subsequent codex-rescue invocations succeed.

Observed impact

  • Zombie task remains in running state forever.
  • All subsequent Agent({ subagent_type: "codex:codex-rescue", ... }) calls return a Chinese-locale message:

    任务 task-mp9b4g4b-rt35lr 仍在运行中,无法续接。请先用 /codex:status 查看当前状态,等任务完成或停止后再续接。 (English: Task task-mp9b4g4b-rt35lr is still running and cannot be continued. Use /codex:status to check the current state and wait for the task to complete or stop before continuing.)

  • The user has no working recovery path except killing Node processes manually from cmd.exe or restarting Claude Code.
  • Worktree directory leaks: .claude/worktrees/magical-allen-6b883c remained after 24+ hours.

Root cause hypothesis

Looking at the codex-companion.mjs bundle around the spawn call (~line 643):

const child = spawn(process.execPath, [scriptPath, "task-worker", "--cwd", cwd, "--job-id", jobId], {
  ...
});

The script spawns child workers. The cancel path likely uses process.kill(pid) or child.kill(), which on Windows defers internally to taskkill /T /F /PID <pid>. If that internal call (or any direct spawn("taskkill", [...], { shell: true })) inherits Git Bash via process.env.ComSpec or runs under shell, MSYS path conversion mangles /PIDC:/Program Files/Git/PID.

The DEP0190 warning indicates the companion is explicitly using shell: true somewhere when spawning, which is itself a security risk (per the deprecation notice) and the direct cause of the path mangling.

Suggested fixes (any of these would resolve)

Fix A (preferred): Don't use shell: true for taskkill

// Instead of:
spawn("taskkill", ["/PID", pid, "/T", "/F"], { shell: true });

// Use:
spawn("taskkill", ["/PID", String(pid), "/T", "/F"], { shell: false });

taskkill is a native Windows command on PATH; no shell is needed. This also clears the DEP0190 warning.

Fix B: Force MSYS to skip path conversion

If shell: true must be retained for other reasons:

spawn("taskkill", ["//PID", String(pid), "//T", "//F"], {
  shell: true,
  env: { ...process.env, MSYS_NO_PATHCONV: "1" }
});

The double-slash //PID is the MSYS escape convention to prevent path conversion. The env var is belt-and-suspenders.

Fix C: Use cmd.exe explicitly on Windows

const shell = process.platform === "win32" ? "cmd.exe" : "/bin/sh";
spawn(shell, ["/c", `taskkill /PID ${pid} /T /F`], { shell: false });

This sidesteps Git Bash entirely.

Fix D: Use a cross-platform process killer library

E.g. tree-kill handles Windows + macOS + Linux uniformly without manual taskkill invocations.

Workaround for affected users (until fixed)

  1. Open cmd.exe (not Git Bash) as Administrator.
  2. Find the stuck Node PID:
    tasklist | findstr node
  3. Kill it manually:
    taskkill /PID <pid> /T /F
  4. Remove the stale worktree manually:
    rmdir /S /Q "<repo>\.claude\worktrees\<task-name>"
  5. Restart the Claude Code session to clear in-memory task state.

Additional context / related issues

  • The DEP0190 warning is not just informational — it precisely identifies that the underlying spawn({ shell: true }) is the cause. Worth addressing project-wide if other commands use the same pattern.
  • This bug is likely invisible on macOS / Linux because there is no MSYS path conversion. Test coverage should include Windows + Git Bash explicitly.
  • Possibly related: any /codex:<command> that ultimately invokes taskkill or other slash-prefixed Windows commands through shell: true may exhibit the same issue.

Repro test (suggested for codex-companion CI)

// Should pass on Windows when run from a Git Bash environment
test("cancel kills worker via taskkill without path conversion", () => {
  // Simulate Git Bash env: process.env.MSYSTEM = "MINGW64"
  // Spawn worker, then cancel
  // Assert: worker process exits, no "Invalid argument" stderr
});

Reporter context: Encountered while using the codex:codex-rescue subagent in Claude Code for a multi-step Python refactor task. The agent's npm run build step hung on output read after about 20 minutes of normal work. /codex:cancel then failed as described, blocking 1+ hour of subsequent work with no recovery path other than restarting Claude Code.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

  • taskkill actually kills PID 43280 and its child processes.
  • Task task-mp9b4g4b-rt35lr transitions to cancelled state.
  • Worktree .claude/worktrees/<task-name> is cleaned up.
  • Task slot is released; subsequent codex-rescue invocations succeed.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix codex-companion cancel fails on Windows + Git Bash due to MSYS path conversion