Summary
When allowed_non_write_users != "" is set and the action runs on a self-hosted runner image that installs supply-chain interception shims for package managers under /usr/bin/ (e.g. any runner with safe-chain enabled, which installs a pkg-bundled Node wrapper at /usr/bin/bun), the action's Post buffered inline comments post-step fails reliably with:
Error: Cannot find module '/home/runner/work/<repo>/<repo>/bun'
at Module._resolveFilename (node:internal/modules/cjs/loader:1207:15)
at Function._resolveFilename (pkg/prelude/bootstrap.js:1950:46)
at Function.runMain (pkg/prelude/bootstrap.js:1978:12)
##[error]Process completed with exit code 1.
The main action step (Run Claude Code Action) completes successfully — review comments are posted via the action's normal flow. Only the post-step cleanup fails.
Root cause (verified against action.yml at v1.0.133)
allowed_non_write_users != "" triggers two composite sub-steps:
Pin bun binary for post-steps — cp $(command -v bun) $GITHUB_ACTION_PATH/bin/bun. continue-on-error: true.
Prepend system bin dirs to PATH — echo "/usr/bin" >> "$GITHUB_PATH"; echo "/bin" >> "$GITHUB_PATH".
On runners that intercept package managers at /usr/bin/ (safe-chain installs a pkg-bundled Node wrapper at /usr/bin/bun), step 2 puts that shim ahead of the real setup-bun-installed bun (/home/runner/.bun/bin/bun) in $PATH.
The post-step then runs:
BUN_BIN="${GITHUB_ACTION_PATH}/bin/bun"
[ -x "$BUN_BIN" ] || BUN_BIN="bun"
"$BUN_BIN" --no-env-file \
--config="${GITHUB_ACTION_PATH}/bunfig.toml" \
--tsconfig-override="${GITHUB_ACTION_PATH}/tsconfig.json" \
run ${GITHUB_ACTION_PATH}/src/entrypoints/post-buffered-inline-comments.ts
If the pin step's cp succeeded, $BUN_BIN is the real bun and this works. But on these runners, the pin step's command -v bun apparently resolves to the safe-chain shim (because the runner has already configured /usr/bin in PATH at action start), so the cp produces a copy of the shim, not real bun. The shim receives bun's CLI args (--no-env-file ... run <ts>), treats the first non-flag arg as a Node module name, and crashes with MODULE_NOT_FOUND.
The stack trace's pkg/prelude/bootstrap.js is Vercel pkg's runtime — real bun is a Zig binary and would never produce this trace, confirming the binary that ran is a Node-app shim, not real bun.
Suggested fixes (any one)
-
Pin step: resolve bun via the bundled setup-bun install dir explicitly, not via command -v. E.g. cp "$BUN_INSTALL/bin/bun" "$GITHUB_ACTION_PATH/bin/bun" where $BUN_INSTALL is set by oven-sh/setup-bun. This avoids whatever PATH-shadowed bun the runner provides.
-
Post-step: use an absolute path that bypasses PATH entirely (you already do this in the main step via ${GITHUB_ACTION_PATH}/bin/bun, but the fallback path "bun" re-introduces the PATH lookup).
-
PATH-prepend step: append /usr/bin and /bin rather than prepend, so the setup-bun-installed bun stays first. This keeps the security hardening intent (system bins always available) without shadowing tools the action explicitly installed.
Reproduction
- Runner: any image that installs supply-chain shims at
/usr/bin/ for package managers (e.g. a runner with safe-chain enabled, which installs a pkg-bundled Node wrapper at /usr/bin/bun).
- Workflow: any usage of this action with
allowed_non_write_users: "*" (or any non-empty value) set.
- Result: action's main step succeeds and posts comments;
Post buffered inline comments post-step fails with MODULE_NOT_FOUND for bun.
Workaround in caller
Set continue-on-error: true on the action step. Substantive review functionality still works (top-level comments are posted by the main step). Inline-comment posting via mcp__github_inline_comment__create_inline_comment is lost (buffered to disk but never flushed to GitHub).
Summary
When
allowed_non_write_users != ""is set and the action runs on a self-hosted runner image that installs supply-chain interception shims for package managers under/usr/bin/(e.g. any runner withsafe-chainenabled, which installs a pkg-bundled Node wrapper at/usr/bin/bun), the action'sPost buffered inline commentspost-step fails reliably with:The main action step (
Run Claude Code Action) completes successfully — review comments are posted via the action's normal flow. Only the post-step cleanup fails.Root cause (verified against
action.ymlat v1.0.133)allowed_non_write_users != ""triggers two composite sub-steps:Pin bun binary for post-steps—cp $(command -v bun) $GITHUB_ACTION_PATH/bin/bun.continue-on-error: true.Prepend system bin dirs to PATH—echo "/usr/bin" >> "$GITHUB_PATH"; echo "/bin" >> "$GITHUB_PATH".On runners that intercept package managers at
/usr/bin/(safe-chain installs a pkg-bundled Node wrapper at/usr/bin/bun), step 2 puts that shim ahead of the realsetup-bun-installed bun (/home/runner/.bun/bin/bun) in$PATH.The post-step then runs:
If the pin step's
cpsucceeded,$BUN_BINis the real bun and this works. But on these runners, the pin step'scommand -v bunapparently resolves to the safe-chain shim (because the runner has already configured/usr/binin PATH at action start), so the cp produces a copy of the shim, not real bun. The shim receives bun's CLI args (--no-env-file ... run <ts>), treats the first non-flag arg as a Node module name, and crashes withMODULE_NOT_FOUND.The stack trace's
pkg/prelude/bootstrap.jsis Vercelpkg's runtime — real bun is a Zig binary and would never produce this trace, confirming the binary that ran is a Node-app shim, not real bun.Suggested fixes (any one)
Pin step: resolve
bunvia the bundled setup-bun install dir explicitly, not viacommand -v. E.g.cp "$BUN_INSTALL/bin/bun" "$GITHUB_ACTION_PATH/bin/bun"where$BUN_INSTALLis set byoven-sh/setup-bun. This avoids whatever PATH-shadowedbunthe runner provides.Post-step: use an absolute path that bypasses PATH entirely (you already do this in the main step via
${GITHUB_ACTION_PATH}/bin/bun, but the fallback path"bun"re-introduces the PATH lookup).PATH-prepend step: append
/usr/binand/binrather than prepend, so the setup-bun-installed bun stays first. This keeps the security hardening intent (system bins always available) without shadowing tools the action explicitly installed.Reproduction
/usr/bin/for package managers (e.g. a runner withsafe-chainenabled, which installs a pkg-bundled Node wrapper at/usr/bin/bun).allowed_non_write_users: "*"(or any non-empty value) set.Post buffered inline commentspost-step fails withMODULE_NOT_FOUNDforbun.Workaround in caller
Set
continue-on-error: trueon the action step. Substantive review functionality still works (top-level comments are posted by the main step). Inline-comment posting viamcp__github_inline_comment__create_inline_commentis lost (buffered to disk but never flushed to GitHub).