Fast Codex exits can crash the action with an unhandled stdin EPIPE
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.2k
- Forks
- 170
- PR merge metrics
- No merged PRs in 30d
Description
Summary
runCodexExec() writes the full prompt to the child stdin pipe without observing errors from that writable stream:
const child = spawn(program, command, {
env,
stdio: ["pipe", "inherit", "inherit"],
});
child.stdin.write(input);
child.stdin.end();
If codex exits before consuming the prompt, a sufficiently large pending write emits EPIPE on child.stdin. Because that EventEmitter has no error listener, Node treats it as an uncaught error and terminates the action helper instead of rejecting through the existing execution promise.
Reproduction / evidence
Current main is 86365089eb2b84e0a8fb0717b304f8bdcb13b20e.
The same pipe lifecycle can be reproduced without network access:
const { spawn } = require("node:child_process");
const child = spawn(process.execPath, ["-e", "process.exit(7)"], {
stdio: ["pipe", "ignore", "ignore"],
});
child.stdin.write("x".repeat(64 * 1024 * 1024));
child.stdin.end();
Current result is an uncaught Error: write EPIPE emitted by the stdin Socket.
Expected behavior
Stdin write failures should reject the same promise that supervises child startup and exit. The action should fail once with a controlled diagnostic, without an uncaught EventEmitter error.
Suggested fix
Observe child.stdin errors and settle the execution promise through the existing rejection path. Ensure a later close event cannot replace the first failure. Add a fake-Codex regression that exits before reading a large prompt and verify the helper reports a controlled failure.
Impact
A fast startup failure combined with a buffered prompt can crash the wrapper for a secondary pipe error, obscuring the actual Codex exit and bypassing normal cleanup/error handling.
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 at runCodexExec() and trace the existing promise that supervises child startup and exit, then review the child.stdin lifecycle shown in the issue. Add the fake-Codex regression with a large prompt and early exit; done means the helper reports one controlled failure without an uncaught EPIPE or a later close replacing it.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github-actions, node.js, typescript
- Domain
- ci-cd
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100