[BUG] isolation: "worktree" — only 1 of 7 concurrent worktrees branched from current HEAD; other 6 used origin/HEAD
Summary
When 7 sub-agents are spawned in a single Agent tool call with isolation: "worktree" and run_in_background: true, 6 of 7 worktrees were created from origin/HEAD (a remote branch unrelated to the active local branch) instead of the current HEAD. The 7th worktree was correctly based on current HEAD — and the only observable difference for that one was that the parent Claude personally extended its state (added a file) before any other ops ran.
This is a near-duplicate of #48095 (origin/HEAD instead of HEAD) and #61264 (concurrent agents on stale commits), but adds new evidence: the bug is not deterministic across a parallel spawn batch — one worktree out of seven escaped it, suggesting a race or a code path dependent on parent activity rather than a pure default-ref bug.
Reproduction
- Repo with two long-lived branches (
beta/5.6.xandbeta/6.0.x);origin/HEAD→beta/5.6.x - Check out feature branch:
git checkout beta/6.0.x(current HEAD =3f34cbb0) - Make a local commit on the feature branch that isn't yet pushed
- In a single Agent tool invocation, spawn 7 sub-agents with
isolation: "worktree"andrun_in_background: true - Each sub-agent:
git rev-parse HEADas the first command in its worktree
Expected: all 7 print 3f34cbb0 (current HEAD).
Observed: 1 prints 3f34cbb0; 6 print 4cc3b9fa — the tip of beta/5.6.x (= origin/HEAD).
The asymmetry (the novel part)
Of the 7 sub-agents, only the one whose worktree was extended by the parent Claude (the parent did a Write into that worktree shortly after spawn, before any other agents started touching their worktrees) was based on the correct HEAD. The other 6 were all based on origin/HEAD.
This could be:
- A race in worktree base-ref resolution during concurrent spawn
- A code path that's only exercised when the parent interacts with the worktree before the child does
- Coincidence (n=1)
Worth investigating because the existing similar bugs (#48095, #61264) describe a consistent wrong-base; this batch was inconsistent.
Impact
Near-miss SEV2. The 6 wrong-based agents each made small, individually-correct lint-cleanup diffs — but on top of beta/5.6.x instead of beta/6.0.x. If merged via classic merge, would have regressed:
- App version
6.0.0+468 → 5.6.5+457 - Flutter SDK floor
>=3.44.0 → >=3.35.0 - 50+ package version pins downgraded
- Workspace plugin
face_liveness_nativeremoved flutter_localizationscommented out
Caught downstream when the squash-merge chain hit a gitea update_branch 409 conflict. ~70 min of cherry-pick recovery. No regression reached the protected branch.
Environment
- Platform: macOS (Darwin 25.5.0)
- Claude Code:
2.1.150 - Date: 2026-05-26
Workaround
Pre-flight check in each sub-agent prompt:
First, run: git rev-parse HEAD
Expected base SHA: <pass-in-from-parent>
If they don't match, STOP and report the actual SHA. Do not proceed.
Also helpful (from #48095): a PreToolUse hook on Agent that runs git remote set-head origin "$(git branch --show-current)" so origin/HEAD tracks the active branch.
Related
- #48095 —
isolation: "worktree"branches fromorigin/HEAD(same root cause) - #61264 — concurrent agents on stale commits (same symptom class)
- #62309 —
claude --worktreebases onorigin/<default>(CLI variant)
Detailed postmortem
Full timeline, 5-whys, and recovery write-up: shared on request — happy to attach the postmortem .md if useful.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗