[Windows] plugin marketplace add fails to spawn Git when PATH has a stray quote before Git
What version of Codex is running?
codex-cli 0.147.0
What subscription do you have?
N/A — this is a local plugin-marketplace command and reproduces with an isolated CODEX_HOME, before authentication or model use.
Which model were you using?
N/A
What platform is your computer?
Microsoft Windows 10.0.29639 x64 (Windows 11 Pro Insider Preview)
What terminal software are you using?
PowerShell 7.6.4. Also reproduced from Codex Desktop 26.803.10989.0.
What issue are you seeing?
On Windows, codex plugin marketplace add can fail to launch Git even though the same PowerShell process resolves and runs git.exe successfully:
Error: failed to run git clone https://github.com/DietrichGebert/ponytail.git C:\Users\<user>\...\.tmp\marketplaces\.staging\marketplace-add-<id>: program not found
In the affected environment:
where.exe git
C:\Users\<user>\AppData\Local\hermes\git\cmd\git.exe
git --version
git version 2.54.0.windows.1
A direct git clone --depth 1 https://github.com/DietrichGebert/ponytail.git <destination> from that shell also succeeds.
The relevant part of codex doctor --json is:
{
"schemaVersion": 1,
"codexVersion": "0.147.0",
"checks": {
"git.environment": {
"status": "warning",
"summary": "Git repository detected but git executable was not found",
"details": {
"PATH git entries": "0",
"repo detected": "true",
"repo root": "C:\\Users\\<user>\\...\\codex",
"selected git": "not found"
}
},
"runtime.provenance": {
"summary": "running local build on windows-x86_64",
"details": {
"platform": "windows-x86_64",
"version": "0.147.0"
}
},
"system.environment": {
"details": {
"os": "Windows 10.0.29639 (Windows 11 Professional) [64-bit]"
}
}
}
}
Steps to reproduce
The trigger is a single stray trailing quote in a PATH entry before the Git entry. PowerShell still resolves Git, while Rust's Windows PATH parsing does not expose the later entry to std::process::Command.
$codexExe = (Get-Command codex -CommandType Application).Source
$gitDir = Split-Path (Get-Command git -CommandType Application).Source
$env:PATH = 'C:\Program Files\PowerShell\7";' + $gitDir + ';C:\Windows\System32'
$env:CODEX_HOME = Join-Path $env:TEMP ("codex-git-spawn-" + [guid]::NewGuid())
New-Item -ItemType Directory -Path $env:CODEX_HOME | Out-Null
Get-Command git
git --version
& $codexExe plugin marketplace add DietrichGebert/ponytail --json
Observed: PowerShell finds and runs git.exe, but Codex exits 1 with failed to run git clone ...: program not found.
Replacing PATH with a clean $gitDir + ';C:\Windows\System32' makes the same Codex binary and command succeed.
What did you expect to happen?
Codex should clone and register the marketplace when Git is resolvable by the host shell. At minimum, it should diagnose the malformed PATH entry rather than reporting that Git is absent.
Additional information
The inherited PATH contains one unmatched quote at the end of an entry, for example:
C:\Program Files\PowerShell\7";C:\Users\<user>\AppData\Local\hermes\git\cmd;...
On Windows, Rust's quote-aware std::env::split_paths treats the unmatched quote as continuing across later semicolons. Command::new("git") therefore returns NotFound, although PowerShell's executable lookup tolerates this PATH and locates a later git.exe.
The marketplace code launches bare git in these paths:
A conservative patch is prepared and tested locally. It preserves the ordinary bare-git attempt and Windows search order. Only after NotFound, and only for the exact unambiguous case of one stray quote at a PATH-entry boundary, it repairs that quote in a copy of PATH, parses the repaired value with std::env::split_paths, and retries the first existing git.exe by absolute path. It does not mutate the process environment or reinterpret balanced/ambiguous quoted PATH values. The fallback is applied only to marketplace add, upgrade, and plugin-source cloning.
Per the repository's invitation-only contribution policy, I am filing the issue first and will open the prepared PR only if a Codex maintainer invites it.
I searched open and closed issues for the exact error and for marketplace + program-not-found/Git-clone combinations. The closest reports appear related but distinct:
- #21959 reports a generic Windows Desktop custom-marketplace failure but does not expose this CLI error or PATH/spawn evidence.
- #13015 concerns the older Recommended Skills subsystem.
- #15586 affects the Desktop terminal's general process launcher; here Git runs normally in PowerShell.
3 Comments
I have prepared the tested patch on a fork branch for maintainer review: https://github.com/x-n2o/codex/tree/agent/windows-malformed-path-git
The branch is one commit ahead of current upstream
main(588e18aae52bdb35fff94a7760b6b502cf0fd154) and changes only the six files described above. In accordance withdocs/contributing.md, I have not opened a pull request and will wait for an explicit Codex-team invitation.Confirmed the mechanism on
main@ 1f41cc5d92, and it's precisely characterizable: this is Rust standard-library PATH parsing meeting an unmatched quote.The spawn.
marketplace addruns Git as a bareCommand::new("git")(core-plugins/src/marketplace_add/install.rs#L113-L124), which delegates program resolution to Rust std's Windows PATH search — and std splitsPATHwithenv::split_paths, whose Windows parser implements quoted-entry semantics: a"toggles quote state so entries may contain semicolons, and quotes are never part of the path. The consequence of a single unmatched quote is that everything from that quote to the end ofPATH(or the next quote) is consumed into one giant pseudo-entry — every later entry, including your Git directory, simply ceases to exist for the search. PowerShell's own resolution (Win32-style) tolerates the stray quote, which produces your exact split:Get-Command gitworks, Codex reportsprogram not found. Yourcodex doctoroutput corroborates it —"PATH git entries": 0means Codex's PATH walk shares the same parse and saw zero Git entries on a machine wherewhere.exefinds one.Scope note: this isn't specific to Git or
marketplace add— every bareCommand::new(name)spawn in Codex on that machine (plugin executables, stdio MCP servers, helper tools) has the same swallowed-PATH view. Your repro just happens to make it visible through the clone step.Fix shapes:
codex doctor's git check already walks PATH — teaching it to detect an unmatched quote and name the offending entry ("PATH entryC:\Program Files\PowerShell\7"contains an unbalanced quote; subsequent entries are ignored by Codex's program resolution") converts a mystifying failure into a 30-second user fix. This is your minimum ask and the cheapest change.split(';')+ quote-stripped walk (or shells out towhere.exe) — matching what users' shells do. There's precedent for a resolution shim in-tree (resolve_windows_programintui/src/external_editor.rs, currently only handling.cmd/.bat); centralizing it would cover all spawn sites at once.program not found— "found 0 candidate directories containing git" reads very differently from "git is not installed".On Windows,
codex plugin marketplace addcan fail to find Git even whenwhere.exe gitworks. A stray unmatched quote in PATH is enough: Rustsplit_pathsswallows every later entry, including Git.Method:
".where.exe gitstill works, then retrycodex plugin marketplace add.Evidence: marketplace add uses bare
Command::new("git"). Rust's Windows PATH parser treats"as quote state, so one unmatched quote hides every later directory. PowerShell's own resolver still finds Git, which is why the two disagree.Independent community workaround; not an official OpenAI fix.