openai / openai/codex-plugin-cc
EAGAIN crash in hook scripts: readFileSync(0) fails when stdin is non-blocking
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Description
Both stop-review-gate-hook.mjs and session-lifecycle-hook.mjs crash intermittently with:
Error: EAGAIN: resource temporarily unavailable, read
at Object.readFileSync (node:fs:449:20)
at readHookInput (file:///.claude/plugins/marketplaces/openai-codex/plugins/codex/scripts/stop-review-gate-hook.mjs:22:18)
Root Cause
readHookInput() uses fs.readFileSync(0, "utf8") to read stdin. When Claude Code invokes hooks with stdin as a pipe in non-blocking mode, the kernel returns EAGAIN instead of blocking. Node.js synchronous APIs don't retry — they throw.
// Both scripts, line 22-23
function readHookInput() {
const raw = fs.readFileSync(0, "utf8").trim(); // throws EAGAIN
if (!raw) { return {}; }
return JSON.parse(raw);
}
Reproduction
Happens intermittently across Claude Code sessions on macOS (Darwin 25.3.0, Node.js v20.19.6). More frequent when multiple hooks fire in quick succession.
Suggested Fix
Catch EAGAIN and treat as empty input:
function readHookInput() {
try {
const raw = fs.readFileSync(0, "utf8").trim();
if (!raw) return {};
return JSON.parse(raw);
} catch (e) {
if (e.code === 'EAGAIN') return {};
throw e;
}
}
Both stop-review-gate-hook.mjs and session-lifecycle-hook.mjs need the same fix.
Environment
- macOS Darwin 25.3.0
- Node.js v20.19.6
- Plugin version: 1.0.2 (commit 8e403f9)
- Claude Code v2.1.90
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 with readHookInput() in stop-review-gate-hook.mjs and session-lifecycle-hook.mjs, where both scripts call fs.readFileSync(0, "utf8"). Reproduce or inspect the EAGAIN path on the documented macOS and Node.js environment. Done means EAGAIN produces empty input in both hooks while other errors still propagate.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100