EnterWorktree(path=...) reports success but wedges/refuses all subsequent Bash calls for a worktree-isolated subagent
Summary
EnterWorktree(path=...) into a pre-created worktree reports success, but subsequent Bash calls into that worktree are refused with an isolation error claiming the command "resolved to the shared checkout" — even though the command targets the exact path EnterWorktree just switched into. Read/Edit/Write and MCP tool calls are unaffected; only the Bash tool's isolation check appears to be reading stale state. The wedge is permanent for the rest of that agent's life — no recovery found.
Environment
Observed during a multi-agent orchestration run (board-auto-develop-style Conductor pattern) using worktree-isolated subagents (Agent(isolation:"worktree")).
Repro steps
- From a top-level session, dispatch a subagent with
Agent(isolation:"worktree")against a git repo. The harness auto-creates a worktree for it. - Separately, in the top-level session (not the subagent), pre-create a second worktree in the same repo via a raw
git worktree add. - Instruct the subagent to call
EnterWorktree(path="<the second, pre-created worktree>"). - The tool call reports success (e.g. "working directory and write access now point at the worktree").
- Have the subagent run a bare
Bashcommand, e.g.pwd, orcd <the pinned path> && pwd.
Expected
The Bash command runs successfully with its cwd resolved to the worktree EnterWorktree just switched into.
Actual
Every subsequent Bash call is refused with an error to the effect of:
This agent is isolated in the worktree<its own auto-created path>, but this command's working directory resolved to the shared checkout (<the EnterWorktree target path>). Refusing to run it there — a worktree-isolated agent's commands must run inside its worktree. Re-run the command from<its own auto-created path>.
Note the error names the EnterWorktree destination path as "the shared checkout" — i.e. as if the switch never took effect from the Bash tool's perspective, even though the EnterWorktree call itself reported success.
Retrying a bare pwd from a clean state (zero other tool calls in between) reproduces the identical error deterministically.
ExitWorktree is also refused when attempted as a recovery path, with an error along the lines of "cannot be called from a subagent with a cwd override... use Bash with cd within it" — i.e. it points back at the exact mechanism (Bash cd) that is already failing.
This was reproduced twice, independently, by two different subagents in the same orchestration run, against two different repos and two different pre-created worktree paths — same failure shape both times.
Hypothesis
EnterWorktree's path-switch appears to update some internal state such that the tool call itself reports success, but the actual cwd-resolution/enforcement logic the Bash tool's isolation check reads remains anchored to the agent's original auto-created worktree. This produces the observed contradiction: the sandbox complains the command "resolved to the shared checkout," treating the EnterWorktree destination as if it were never adopted.
Workaround found
A worktree-isolated subagent should not call EnterWorktree(path=...) to switch into a different, pre-created worktree at all. Instead:
- Dispatch the
Agent(isolation:"worktree")call from a sessioncwdalready inside the correct target location, so the subagent's own auto-created worktree is already correctly rooted — no switch needed. - If a switch is genuinely unavoidable, fall back to MCP-tool-only operations (e.g. a forge's MCP tools for reading/writing files and opening PRs) for anything that would otherwise require
Bash+ the git CLI, sinceRead/Edit/Writeand MCP tool calls were unaffected by theBashwedge in both observed incidents.
Impact
Wastes a full subagent dispatch cycle (both incidents cost significant token spend and several minutes before the blocker surfaced) and requires a supervising session to intervene — either redispatching cleanly, or performing execution-based verification on the stuck subagent's behalf since its Bash tool is unusable for the rest of its life.