Bash tool: PATH not Windows->POSIX translated when MSYS bash subprocess respawns mid-session

Open 💬 2 comments Opened Jun 6, 2026 by philipobermeyer

Summary

Mid-session, after some harness state change, the Bash tool's persistent MSYS bash subprocess starts returning command not found for gh, node, rm, ls, head, which, date, and other binaries. git continues to work. Root cause is that the bash subprocess is spawned with the un-translated Windows-style PATH (semicolon-separated C:\... entries), which MSYS bash cannot parse as POSIX path entries.

The harness then appends a single POSIX-style path at the end with :, producing a malformed mixed-format PATH. Bash treats the entire Windows prefix as one giant non-existent directory name; only the trailing POSIX-appended entry is usable.

Environment

  • Claude Code: 2.1.161 (Electron desktop build)
  • Platform: Windows 11
  • Shell: Git for Windows MSYS bash (C:\Program Files\Git\bin\bash.exe)
  • Symptom appeared mid-session after harness state recovery (correlates with a brief claude-opus-4-7 is temporarily unavailable classifier downtime event ~3 minutes earlier, suggesting bash respawn during recovery)

Reproduction

Inside a long-running session where the Bash tool initially works fine:

  1. Some harness state change occurs (in my case: classifier supervisor downtime + recovery)
  2. The harness re-spawns its persistent bash subprocesses
  3. From this point forward, every Bash tool call observes broken PATH

Evidence — direct $PATH dump from inside Bash tool

(Username + skills-plugin install path redacted for public issue; the structural shape is what matters.)

PATH=C:\Python314\Scripts\;C:\Python314\;C:\Python313\Scripts\;C:\Python313\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\ProgramData\chocolatey\bin;C:\Program Files\Git\cmd;C:\Program Files\nodejs\;C:\Program Files\GitHub CLI\;C:\Users\<user>\AppData\Local\Microsoft\WindowsApps;C:\Users\<user>\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\<user>\AppData\Roaming\npm;C:\Users\<user>\AppData\Local\Programs\Ollama;C:\Users\<user>\.local\bin;C:\Program Files\nodejs;C:\Python314;C:\Python313;C:\Program Files\Git\mingw64\bin:/c/Users/<user>/AppData/Roaming/Claude/local-agent-mode-sessions/skills-plugin/<uuid>/<uuid>/bin

The PATH is almost entirely semicolon-separated Windows C:\... paths — except the very last segment is colon-prefixed POSIX /c/... path appended by the harness for its skills-plugin bin directory.

MSYS bash uses : as the POSIX path separator. So it parses this as two entries:

  1. C:\Python314\Scripts\;C:\Python314\;...;C:\Program Files\Git\mingw64\bin — one giant directory name, doesn't exist on disk
  2. /c/Users/<user>/AppData/Roaming/Claude/local-agent-mode-sessions/skills-plugin/<uuid>/<uuid>/bin — the only valid PATH entry

git happens to live in that plugin bin directory, which is why it keeps working. Everything else fails with command not found.

Process-tree evidence

Two persistent bash.exe subprocesses live for the entire session:

PID <n>    bash  StartTime: 2026-06-06T04:50:08Z (= local 11:50:08 PM)  C:\Program Files\Git\bin\bash.exe
PID <n+1>  bash  StartTime: 2026-06-06T04:50:08Z                        C:\Program Files\Git\bin\..\usr\bin\bash.exe

The session started ~12 hours before the bash respawn. For the first ~12 hours, all gh/node calls in Bash worked correctly. After the respawn at 04:50:08Z, every Bash call has observed the broken PATH.

No ~/.bashrc or ~/.bash_profile exists for the user, so PATH comes purely from what the harness passes via environment when spawning the subprocess.

PowerShell tool (separate Windows subprocess) sees a clean Windows PATH with proper ; separators and works normally.

Suggested fix

In the bash-subprocess spawn code path, translate Windows-style PATH to POSIX before passing to the child process. Something like:

function win32PathToPosix(winPath: string): string {
  return winPath
    .split(';')
    .filter(p => p.length > 0)
    .map(p => {
      // C:\Foo\Bar  ->  /c/Foo/Bar
      const m = p.match(/^([A-Za-z]):[\\/](.*)$/);
      if (m) return `/${m[1].toLowerCase()}/${m[2].replace(/\\/g, '/')}`;
      return p;
    })
    .join(':');
}

// In the bash spawn:
const env = {
  ...process.env,
  PATH: process.platform === 'win32'
    ? win32PathToPosix(process.env.PATH) + ':' + skillsPluginBin
    : process.env.PATH + ':' + skillsPluginBin,
};
spawn(bashPath, args, { env });

The translation needs to apply on every bash subprocess spawn, including respawns triggered by harness state recovery.

Why "intermittent" — the time correlation

In my session, the original bash subprocess (presumably spawned at session start) had a correctly POSIX-translated PATH and worked for ~12 hours. The respawn at 04:50:08Z did not apply the same translation, suggesting the respawn code path is missing the translation step that the initial-spawn code path has. The fix would need to land in whichever code path handles respawn, not just initial spawn.

Workaround

PowerShell tool works (Windows-native PATH semantics, no separator mismatch). For the rest of an affected session, route gh/node/coreutils calls through PowerShell instead of Bash. git calls continue to work in Bash.

Impact

Silent degradation of the Bash tool's capability mid-session, with confusing command not found errors that look like user environment misconfiguration rather than a harness PATH bug. The shell itself still runs (so the tool doesn't "fail"), but most cross-platform tooling becomes unreachable.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗