restoreConfigFromBase ENOENT on .claude/ symlinks whose target is outside SENSITIVE_PATHS (regression after dereference + Bun 1.3.14)

Author: DanOfirCreated May 17, 2026Updated Sep 18, 2026
Labelsbugp1

Summary

restoreConfigFromBase crashes with ENOENT: no such file or directory, statx '<path>' when the snapshotted PR directory contains a symlink whose target lives outside the SENSITIVE_PATHS set (e.g. .claude/skills/<name> → ../../.agents/skills/<name>).

This is a regression introduced on 2026-05-14 by the combination of:

  • #1186 ("fix: dereference symlinks when snapshotting sensitive paths to .claude-pr/", merged 22:36 UTC) — added dereference: true to the cpSync call.
  • #1312 ("chore: bump pinned Bun to 1.3.14", merged 22:55 UTC) — Bun went from 1.3.6 to 1.3.14 in the same v1 rollout (22:56 UTC, commit 51ea8ea).

The earlier fix #1186 closed #1187 / #1220 / #1311, but those issues were all about symlinks whose target is itself a SENSITIVE_PATH entry (e.g. CLAUDE.md → AGENTS.md). The fix does not cover the case here: the symlink lives inside .claude/ but points to a sibling directory (.agents/) that is NOT in SENSITIVE_PATHS, so cpSync with dereference: true follows the symlink and then statx fails the moment it traverses out of the snapshot tree.

Repro

Workflow:

yaml
- uses: anthropics/claude-code-action@v1

Repo layout:

.claude/skills/shadcn  -> ../../.agents/skills/shadcn   # symlink (in repo, tracked as mode 120000)
.agents/skills/shadcn/                                  # real directory (tracked, present after actions/checkout@v5)

Note: the symlink target IS present on disk after checkout — .agents/ is a regular tracked directory in the repo. The failure is not "dangling symlink".

Failure log

Restoring .claude, .mcp.json, .claude.json, .gitmodules, .ripgreprc, CLAUDE.md, CLAUDE.local.md, .husky from origin/master (PR head is untrusted)
##[error]Action failed with error: ENOENT: no such file or directory, statx '.claude/skills/shadcn'

Confirmed timeline

  • Last green run: action SHA 86eb26bf0139bdd75acd15ea5f00f45ee0a284c2, runner bun-version: 1.3.6, 2026-05-14 18:02 UTC.
  • First red run (same workflow, same repo, same symlink): action SHA 51ea8ea73a139f2a74ff649e3092c25a904aed7e, runner bun-version: 1.3.14, 2026-05-15 13:28 UTC.
  • Workflow file and repo symlink unchanged across that window.
  • Every PR in our repo has failed identically since 5/15 (multiple branches and authors).

Hypothesis on the failure mode

In src/github/operations/restore-config.ts:

typescript
for (const p of SENSITIVE_PATHS) {
  if (existsSync(p)) {
    cpSync(p, `.claude-pr/${p}`, { recursive: true, dereference: true });
  }
}

When cpSync recurses into .claude/ and reaches .claude/skills/shadcn, dereference: true makes it follow the symlink and statx the target. Bun 1.3.14 appears to throw on this where 1.3.6 tolerated it — possibly stricter symlink/statx semantics, or an interaction with how Bun materializes the dereferenced path during recursive copy.

(We have not isolated whether the immediate cause is Bun 1.3.14 itself or the dereference: true + Bun 1.3.14 combination, but reverting either piece to the pre-2026-05-14 state restores green CI.)

Suggested directions

  1. Skip individual entries whose resolved target lies outside SENSITIVE_PATHS, or
  2. Wrap each per-entry cpSync in a try/catch that warns and falls back to snapshotting the link as a link (not its content), or
  3. Reproduce against Bun 1.3.14 specifically and report upstream if this is a Bun regression.

Workaround users can apply now

Pin the action to the last good SHA in their workflow:

yaml
uses: anthropics/claude-code-action@86eb26bf0139bdd75acd15ea5f00f45ee0a284c2 # last v1 before 2026-05-14 22:56 UTC

This avoids both the dereference: true change and Bun 1.3.14. Confirmed green again with this pin.

Affected scope

Not a single-repo issue — this hits any repo whose .claude/ includes a symlink pointing outside SENSITIVE_PATHS (a reasonable pattern for sharing prompts/skills between two top-level directories like .claude/ and .agents/).

Source: anthropics/claude-code-action