openai / openai/codex-plugin-cc
`runCommand` sets `maxBuffer: options.maxBuffer` — the ENOBUFS fix from #179 works only because a spread `undefined` deletes Node's default
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Summary
runCommand in plugins/codex/scripts/lib/process.mjs:10 sets maxBuffer: options.maxBuffer. No caller except measureGitOutputBytes (lib/git.mjs:41) ever supplies a value, so for every other command that property is literally undefined.
That is not the same as omitting it. spawnSync builds its options as
options = {
__proto__: null,
maxBuffer: MAX_BUFFER, // 1 MiB
...normalizeSpawnArguments(file, args, options),
};
The spread carries an own maxBuffer property whose value is undefined, which overwrites the 1 MiB default. The result is not "1 MiB" and not "the caller's value" — it is no limit at all.
So #11 and #151 are genuinely fixed on main, but not by the size gate that PR #179 added, and not by anything named in that PR. They are fixed because a property that looks like an inert pass-through happens to delete Node's default. Nothing documents this and no test covers it.
Consequence 1: one refactor away from reopening #11 and #151
Every shape a reader would consider equivalent restores the 1 MiB cap:
maxBuffer: options.maxBuffer ?? MAX, // different
...(options.maxBuffer !== undefined && { maxBuffer: options.maxBuffer }), // different
// or just dropping the line as "it does nothing"
Same repo, same review, only that line changed:
upstream HEAD (maxBuffer: options.maxBuffer) -> OK inputMode=self-collect diffBytes=0
same logic, key omitted when unset -> ENOBUFS spawnSync git ENOBUFS
Consequence 2: the reads that are unbounded are the ones the gate never measures
PR #179's gate measures only the diff, and only to decide inline-diff vs self-collect. These run on every review, before and outside the gate, with no ceiling:
| line | command |
|---|---|
git.mjs:123-125 |
diff --cached --name-only, diff --name-only, ls-files --others --exclude-standard |
git.mjs:227 |
status --short --untracked-files=all |
git.mjs:266-267 |
diff --name-only <range>, log --oneline --decorate <range> |
--untracked-files=all expands every file under every untracked directory, so a repo with an unignored node_modules/, build/ or coverage output produces megabytes of path names while the diff itself is empty. Today that is read into a JS string with no limit; after any of the refactors above it is ENOBUFS. Neither is the intended behaviour, and per #151 an ENOBUFS from binaryAvailable surfaces as the misleading "Codex CLI is not installed".
Repro
git init repro && cd repro
git commit -qm init --allow-empty
mkdir -p build/assets
python3 -c "
import os
for i in range(14000):
open('build/assets/generated_component_with_a_reasonably_long_file_name_%05d.chunk.js' % i, 'w').write('x')
"
git status --short --untracked-files=all | wc -c # 1176000 -> over Node's 1 MiB default
git diff --binary | wc -c # 0 -> the measured gate sees nothing
Then collectReviewContext(cwd, { mode: "working-tree" }) buffers ~1.15 MB of path names on main, and throws ENOBUFS under any of the equivalent-looking rewrites.
Suggested fix
Give the pass-through an explicit, generous default so the ceiling is stated rather than inherited from a spread quirk:
// Node defaults maxBuffer to 1 MiB, which ENOBUFS on any git output larger than that.
maxBuffer: options.maxBuffer ?? 256 * 1024 * 1024,
measureGitOutputBytes still passes its own small bound, so the inline-diff / self-collect gate is unaffected. A regression test asserting that a >1 MiB git status survives runCommand would pin the behaviour that #11 and #151 currently depend on implicitly.
Environment
- codex-plugin-cc:
main@ db52e28 (1.0.6); originally hit on 1.0.2, which had nomaxBufferline at all - Node.js: v24.12.0 and v25.9.0 (identical results)
- macOS arm64
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in plugins/codex/scripts/lib/process.mjs:10 and compare its runCommand options with the caller at lib/git.mjs:41; then inspect the git output calls around lines 123-125, 227, and 266-267. Add a regression test exercising a git status larger than 1 MiB through runCommand, while confirming measureGitOutputBytes keeps its separate bound; done means the large status succeeds without reopening the existing ENOBUFS failures.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, javascript, node.js
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100