openai / openai/codex-plugin-cc

EAGAIN crash in hook scripts: readFileSync(0) fails when stdin is non-blocking

Open Beginner friendly
#120 5 comments 0 reactions 0 assignees View on GitHub

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.