`bgIsolation` guard recovery path is broken: error tells agents to call `EnterWorktree`, which is a deferred tool

Status Fixed / completed
Maintainer reply ✓ Yes — bogini
Activity 4 comments · opened May 26, 2026 · closed May 27, 2026
💡 Likely answer: A maintainer (bogini, collaborator) responded on this thread — see the highlighted reply below.

Summary

The bgIsolation guard refuses Edit/Write in a background session that hasn't called EnterWorktree, and the error tells the agent the recovery path:

"This background session hasn't isolated its changes yet. Call EnterWorktree first so edits land in a worktree instead of the shared checkout, then retry this edit using the worktree path."

But EnterWorktree is a deferred tool in current Claude Code (its schema is not loaded; it must be fetched via ToolSearch first). The guard message doesn't mention this. Agents that follow the instruction literally either:

  1. Call EnterWorktree directly and get InputValidationError (tool not loaded), or
  2. Don't connect "the worktree path" with "the cwd EnterWorktree returns," re-issue Edit on the original path, hit the guard again, and bail.

End-result: from the user's perspective, the Edit tool appears to return a mysterious internal error and subagents stall. The first error message (the actual guard) gets buried under a follow-on InputValidationError, so the user-visible symptom is just "Edit broke."

Environment

  • Claude Code v2.1.150
  • Windows 11 Pro 10.0.26200, PowerShell
  • Subagents dispatched via the vanilla Agent tool (no isolation parameter set)
  • Project has no .claude/settings.json override for worktree.bgIsolation

Evidence from session logs

Deferred-tool list shown to background sessions (confirmed in this session's SessionStart system reminder) includes EnterWorktree:

"The following deferred tools are now available via ToolSearch. Their schemas are NOT loaded — calling them directly will fail with InputValidationError: CronCreate, CronDelete, ... EnterWorktree, ExitWorktree, ..."

Guard fire from a background session transcript under ~/.claude/projects/<project>/<session>.jsonl:

[191] tool_use Write {"file_path": "<repo>\\.mise.local.toml"}
[192] tool_result ERR: <tool_use_error>This background session hasn't isolated its changes yet.
       Call EnterWorktree first so edits land in a worktree instead of the shared checkout,
       then retry this edit using the worktree path. (To disable this guard for this repo,
       set `"worktree": {"bgIsolation": "none"}` in .claude/settings.json.)</tool_use_error>
[194] text: "The background isolation guard won't let me write directly to your main checkout
       — but this is a 4-line file, so let me just give you the command. Paste this into your
       PowerShell at the repo root: ..."

Note step 194: the agent did not attempt ToolSearch + EnterWorktree. It rationalized failure and asked the user to run the command manually. This is the recovery the guard's message implicitly relies on, and it doesn't happen.

Repro

  1. Start a background claude session in a git repo (no worktree.bgIsolation override).
  2. From the parent session, dispatch a subagent with Agent and instruct it to write a small new file (no isolation: "worktree").
  3. Observe: the subagent's first Edit/Write returns the guard error, and the subagent typically either errors with InputValidationError on a direct EnterWorktree call or gives up and tells the user to run the command themselves.

Suggested fixes (any one helps; ideally all three)

  1. Make the guard message reference ToolSearch. Something like:

> "Call EnterWorktree first (load its schema via ToolSearch({query: "select:EnterWorktree"}) if not already available), then retry this edit using the path returned by EnterWorktree."

  1. Pre-load EnterWorktree's schema in any session where the bgIsolation guard can fire. The agent shouldn't need a hop to reach its own documented recovery path.
  2. Default Agent subagent dispatches to isolation: "worktree" when the dispatched agent has Edit/Write in its tool allowlist, OR inherit the parent's worktree state. Today the parent session can be in a worktree but the subagent it spawns isn't, which is surprising.

Why this is worse than it looks

The user-visible symptom is "Edit returns an internal error" — the actual guard text is hidden inside the subagent's transcript and not surfaced to the parent. Users don't realize there's a guard at all; they just see flaky parallel agents. In my data this is biting across multiple sessions on the same machine. Compounding bug #59848 (bg guards firing on foreground sessions on some platforms), this will become a frequent confusion source.

Related (but distinct) issues

  • #59848 — interactive sessions classified as background, causing bg-only guards to fire (different root cause; same downstream UX)
  • #58507 (closed) — catch-22 when cwd is already a worktree
  • #59580 — worktree.bgIsolation setting missing from docs
  • #58435 (closed) — opt-out for forced-worktree enforcement

View original on GitHub ↗

4 Comments

jshaofa-ui · 4 months ago

1|# claude-code #62372: bgIsolation Guard Recovery Path Broken — EnterWorktree is Deferred
2|
3|## Issue Summary
4|
5|The bgIsolation guard refuses Edit/Write in a background session that hasn't called EnterWorktree, and the error message tells the agent to call EnterWorktree first. However, EnterWorktree is a deferred tool — its schema is not loaded in background sessions and must be fetched via ToolSearch first. Agents that follow the guard's instruction literally either:
6|1. Call EnterWorktree directly → InputValidationError (tool not loaded)
7|2. Don't connect "the worktree path" with "the cwd EnterWorktree returns" → hit the guard again
8|
9|End result: from the user's perspective, the Edit tool appears to return a mysterious internal error and subagents stall.
10|
11|## Root Cause Analysis
12|
13|### The Deferred Tool Gap
14|Background sessions have a limited tool set. EnterWorktree is listed as a deferred tool in the SessionStart system reminder:
15|> *"The following deferred tools are now available via ToolSearch. Their schemas are NOT loaded — calling them directly will fail with InputValidationError: ... EnterWorktree, ExitWorktree, ..."
16|
17|The guard's error message references EnterWorktree by name but does not instruct the agent to first load its schema via ToolSearch. This creates an unrecoverable state because:
18|1. The agent doesn't know EnterWorktree needs to be searched for first
19|2. Even if it does, the agent may not connect the worktree path returned by EnterWorktree with the path it should use for subsequent edits
20|
21|### Why This Is Worse Than It Looks
22|The user-visible symptom is "Edit returns an internal error" — the actual guard text is hidden inside the subagent's transcript. Users don't realize there's a guard at all; they just see flaky parallel agents.
23|
24|## Proposed Fix
25|
26|### Fix 1: Enrich Guard Message with ToolSearch Instructions (Quick Win)
27|
28|Modify the guard error message to include explicit ToolSearch instructions:
29|
30|``diff
31|- "This background session hasn't isolated its changes yet. Call EnterWorktree first so edits land in a worktree instead of the shared checkout, then retry this edit using the worktree path."
32|+ "This background session hasn't isolated its changes yet. To isolate changes: (1) Call ToolSearch({query: 'select:EnterWorktree'}) to load the EnterWorktree tool, (2) Call EnterWorktree() to create a worktree and get its path, (3) Retry your edit using the worktree path returned by EnterWorktree. (To disable this guard for this repo, set
\"worktree\": {\"bgIsolation\": \"none\"} in .claude/settings.json.)"
33|
`
34|
35|### Fix 2: Pre-Load EnterWorktree Schema in bgIsolation Contexts (Proper Fix)
36|
37|When the
bgIsolation guard can fire in a session, pre-load the EnterWorktree and ExitWorktree tool schemas so they're immediately available without a ToolSearch hop:
38|
39|
`typescript
40|// In session initialization for background sessions with bgIsolation enabled
41|if (session.isBackground && config.worktree?.bgIsolation !== 'none') {
42| // Pre-load worktree tools since the bgIsolation guard references them
43| await loadToolSchemas(['EnterWorktree', 'ExitWorktree']);
44|}
45|
`
46|
47|This ensures the recovery path mentioned in the guard message is actually executable.
48|
49|### Fix 3: Default Agent Subagent Dispatch to Worktree Isolation (Best UX)
50|
51|When dispatching an
Agent subagent that has Edit/Write in its tool allowlist, default to isolation: "worktree":
52|
53|
`typescript
54|// In Agent tool dispatch logic
55|function dispatchAgent(params: AgentDispatchParams) {
56| const hasWriteTools = params.tools?.some(t => ['Edit', 'Write', 'MultiEdit'].includes(t));
57|
58| if (hasWriteTools && !params.isolation) {
59| // Default to worktree isolation for agents that can write files
60| params.isolation = 'worktree';
61| }
62|
63| // Also inherit parent's worktree state if already in a worktree
64| if (session.worktreePath && !params.isolation) {
65| params.isolation = 'worktree';
66| params.worktreePath = session.worktreePath;
67| }
68|
69| return createSubagent(params);
70|}
71|
`
72|
73|This prevents the guard from firing in the first place by ensuring subagents that need to write files are automatically isolated.
74|
75|### Fix 4: Guard Message Should Surface to Parent Session (UX Improvement)
76|
77|The guard text is currently buried in the subagent's transcript. Surface it to the parent session:
78|
79|
`typescript
80|// When bgIsolation guard fires in a subagent
81|if (guardFired && session.isSubagent) {
82| // Include guard context in the error returned to parent
83| return {
84| type: 'tool_result',
85| content: error,
86| _guardContext: {
87| type: 'bgIsolation',
88| message: guardMessage,
89| recoverySteps: ['ToolSearch(EnterWorktree)', 'EnterWorktree()', 'Retry edit with worktree path']
90| }
91| };
92|}
93|
`
94|
95|## Implementation Priority
96|
97|1. **P1 (Important)**: Enrich guard message with ToolSearch instructions — quick fix, ~10 lines
98|2. **P1 (Important)**: Pre-load EnterWorktree schema in bgIsolation contexts — proper fix, ~50 lines
99|3. **P0 (Critical)**: Default Agent dispatch to worktree isolation — prevents the issue entirely, ~30 lines
100|4. **P2 (Enhancement)**: Surface guard context to parent session — UX improvement, ~20 lines
101|
102|## Testing Plan
103|
104|1. **Unit tests**: Verify guard message includes ToolSearch instructions
105|2. **Integration tests**: Dispatch subagent with Edit/Write tools → verify worktree isolation is default
106|3. **Regression tests**: Verify existing
isolation: "none" and isolation: "worktree"` explicit settings still work
107|4. End-to-end tests: Background session → dispatch agent → write file → verify no guard fires
108|
109|## Impact
110|
111|- User impact: HIGH — Users see "Edit broke" with no actionable error message
112|- Scope: Medium — Affects all background session + Agent tool combinations on Windows
113|- Fix complexity: LOW — Message change + pre-load logic, ~100 lines total
114|- Related issues: #59848 (bg guards firing on foreground), #58507 (closed, worktree catch-22)
115|

jshaofa-ui · 4 months ago

Solution: Fix bgIsolation Guard Recovery Path

Root Cause

The bgIsolation guard's error message tells agents to "Call EnterWorktree first" but EnterWorktree is a deferred tool — its schema isn't loaded by default and must be fetched via ToolSearch. Agents that follow the instruction literally get InputValidationError, masking the original guard message.

Fix

Two-part fix:

  1. Update error message to include complete recovery path:
This background session hasn't isolated its changes yet.
To recover:
1. Call ToolSearch with query "EnterWorktree" to load the tool schema
2. Call EnterWorktree to create an isolated worktree
3. Use the worktree path returned by EnterWorktree for subsequent Edit/Write calls
Note: EnterWorktree is a deferred tool — discover it via ToolSearch first.
  1. Ensure EnterWorktree is listed in the deferred tool list shown to background sessions in SessionStart system prompt.

Why This Works

  • Complete instructions: Agents get the full recovery path including ToolSearch step
  • No error masking: Agents discover the tool before calling it
  • Minimal change: Only error message and system prompt update needed

Files Changed

  • Background session guard handler — Update error message with ToolSearch step
  • SessionStart system prompt — Ensure EnterWorktree is listed as deferred tool
bogini collaborator · 4 months ago

Addressed by a merged fix. Please reopen with a fresh repro if you still see this on a current version.

github-actions[bot] · 2 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.