Summary
ctx_execute (and ctx_execute_file) fail to spawn the python, python3, and node language runners on Windows when the only interpreters resolvable on PATH are Git-for-Windows-style POSIX shell-script shims (the common shape produced by pyenv-win, some Python launcher setups, and Git Bash's own /usr/bin/python* wrappers). The tool reports Executable not found in $PATH: "python", which is misleading and sent me down a multi-hour path of "fix your PATH" when the interpreters were already valid and resolvable by every other tool on the machine (bash, which, etc.).
Root cause
The language runner spawns the interpreter via a native Windows process-creation call with no shell mediation (Node/Bun child_process.execFileSync/spawn with shell:false, effectively CreateProcess). That resolution path:
- Requires the target to have a real extension (
.exe/.com/.bat/.cmd) — a bare extensionless file (even a valid, executable-via-bash POSIX shell script) is invisible to it.
- Does not fall back to a shell (
cmd.exe) that would have resolved PATHEXT correctly and executed the shim.
So on any Windows box where Python/Node were installed via a wrapper-script pattern (extensionless, shebang-based python/python3/node on PATH, common with Git for Windows), ctx_execute(language:"python") and ctx_execute(language:"javascript") fail outright even though the interpreter is fully functional and on PATH for every other purpose.
Reproduction
Environment: Windows 11, Git for Windows (MSYS2) installed, Python 3.14 and Node 24 installed via their official installers but exposed on PATH only through Git Bash-style #!/bin/sh wrapper scripts at C:\Program Files\Git\usr\bin\python, python3, node (no .exe extension).
ctx_execute(language: "python", code: "print(1)")
Result:
Exit code: 1
stderr:
Executable not found in $PATH: "python"
Yet in the same environment:
ctx_execute(language: "shell", code: "python --version")
succeeds and prints Python 3.14.7, because bash resolves the extensionless shim directly.
I also reproduced the identical failure shape independently for node:
// ctx_execute(language: "javascript")
const { execFileSync } = require('child_process');
execFileSync('node', ['--version'], { shell: false }); // throws "Executable not found in $PATH: node"
while execFileSync('node', ['--version']) succeeds when a real .exe is on PATH.
Impact
- The error message ("not found in $PATH") is actively misleading: the executable is found by every other consumer of
PATH on the machine. The actual condition is "found, but not natively spawnable without shell mediation."
- This silently breaks
ctx_execute(language:"python"/"javascript"/"typescript") for a fairly common real-world Windows dev environment shape (Git for Windows + python.org/nodejs.org installers, no bundled/embedded interpreter), with no actionable guidance in the error toward the real cause.
- Working around it currently requires hand-placing hard-linked
.exe files (and, for CPython specifically, the interpreter's dependent DLL) directly into a directory already on the restricted PATH the sandboxed spawn actually inherits — which is a fragile, environment-specific hack, not something a normal user should have to reverse-engineer.
Suggested fix
For the python/node/etc. language runners on Windows, either:
- Fall back to a shell-mediated spawn (
shell: true, or explicit cmd.exe /c) when a direct non-shell spawn reports "not found," before surfacing an error, so PATHEXT-based and shim-based resolution gets a chance; or
- At minimum, distinguish in the error message between "no candidate found on PATH at all" and "a candidate exists on PATH but couldn't be spawned without shell mediation" (e.g. by doing a
where/command -v-equivalent check first), so users aren't misdirected into "fix your PATH" when PATH was never the problem.
Environment
context-mode v1.0.169
- OS: Windows 11
- Shell integration: Git for Windows / MSYS2 (Git Bash)
ctx_doctor output at time of report:
[OK] Runtimes: 5/11 (45%) — javascript, shell, typescript, python, rust
[OK] Performance: FAST (Bun)
[OK] Server test: PASS
[OK] FTS5 / SQLite: PASS — native module works
(Runtime detection reported these as "OK" despite the underlying native spawn failing — the detection check itself appears to accept a shim that the actual exec path can't use, which is worth verifying as a related gap.)
Summary
ctx_execute(andctx_execute_file) fail to spawn thepython,python3, andnodelanguage runners on Windows when the only interpreters resolvable onPATHare Git-for-Windows-style POSIX shell-script shims (the common shape produced bypyenv-win, some Python launcher setups, and Git Bash's own/usr/bin/python*wrappers). The tool reportsExecutable not found in $PATH: "python", which is misleading and sent me down a multi-hour path of "fix your PATH" when the interpreters were already valid and resolvable by every other tool on the machine (bash,which, etc.).Root cause
The language runner spawns the interpreter via a native Windows process-creation call with no shell mediation (Node/Bun
child_process.execFileSync/spawnwithshell:false, effectivelyCreateProcess). That resolution path:.exe/.com/.bat/.cmd) — a bare extensionless file (even a valid, executable-via-bash POSIX shell script) is invisible to it.cmd.exe) that would have resolvedPATHEXTcorrectly and executed the shim.So on any Windows box where Python/Node were installed via a wrapper-script pattern (extensionless, shebang-based
python/python3/nodeonPATH, common with Git for Windows),ctx_execute(language:"python")andctx_execute(language:"javascript")fail outright even though the interpreter is fully functional and onPATHfor every other purpose.Reproduction
Environment: Windows 11, Git for Windows (MSYS2) installed, Python 3.14 and Node 24 installed via their official installers but exposed on
PATHonly through Git Bash-style#!/bin/shwrapper scripts atC:\Program Files\Git\usr\bin\python,python3,node(no.exeextension).Result:
Yet in the same environment:
succeeds and prints
Python 3.14.7, because bash resolves the extensionless shim directly.I also reproduced the identical failure shape independently for
node:while
execFileSync('node', ['--version'])succeeds when a real.exeis onPATH.Impact
PATHon the machine. The actual condition is "found, but not natively spawnable without shell mediation."ctx_execute(language:"python"/"javascript"/"typescript")for a fairly common real-world Windows dev environment shape (Git for Windows + python.org/nodejs.org installers, no bundled/embedded interpreter), with no actionable guidance in the error toward the real cause..exefiles (and, for CPython specifically, the interpreter's dependent DLL) directly into a directory already on the restrictedPATHthe sandboxed spawn actually inherits — which is a fragile, environment-specific hack, not something a normal user should have to reverse-engineer.Suggested fix
For the
python/node/etc. language runners on Windows, either:shell: true, or explicitcmd.exe /c) when a direct non-shell spawn reports "not found," before surfacing an error, soPATHEXT-based and shim-based resolution gets a chance; orwhere/command -v-equivalent check first), so users aren't misdirected into "fix your PATH" when PATH was never the problem.Environment
context-modev1.0.169ctx_doctoroutput at time of report: