Dispatch start_code_task still blocked in 1.49585.0: opening a finished session in the UI re-locks the folder (follow-up to #91745, #92452, #92462)
Summary
On desktop 1.49585.0 (Linux), Dispatch start_code_task is refused again with:
Failed to start code session: A Claude Code session (local_4c2ba47d-...) is already active in this directory.
The stale-record half of #91745 / #92462 is genuinely fixed in this build: findActiveSessionByCwd now skips records that have no live query, and the 200 non-archived records sharing this folder no longer block anything. Thank you for that.
What remains is that a finished session becomes a blocker again the moment it is opened in the app. Selecting it in the Code tab warms it, re-attaches a CLI process, and that idle session then holds the folder against Dispatch. In this case the blocking session had completed its last turn 47 minutes earlier and had already been stopped by the app.
Meanwhile four sessions, two of them app-local, were running concurrently in that same folder without any problem. The exclusivity is enforced only on the Dispatch path, where exclusiveCwd: true is still hardcoded.
What is fixed and what is not
1.46388.2 blocked on any non-archived record (see #92462). 1.49585.0 narrows it:
findActiveSessionByCwd(e,t){
let n=this.startingSessionCwds.get(e);
if(n){for(let e of n.keys())if(e!==t)return e}
for(let n of this.heldSessions())
if(!(n.isArchived || !n.query && !n.startResumeInFlight || n.sessionId===t)
&& (this.normalizeCwdKey(n.originCwd||n.cwd,n.backend.remoteTarget)===e
|| n.originCwd && n.originCwd!==n.cwd && this.normalizeCwdKey(n.cwd,n.backend.remoteTarget)===e))
return n.sessionId
}
query is present for any warmed session, including an idle one with no pending turn, and warming happens when the user merely selects the session in the UI. The caller is unchanged:
startCodeSession: ... o.startSession({...}, {dispatchParentId:r, dispatchParentOrigin:"local", ..., exclusiveCwd:!0})
exclusiveCwd is set here and nowhere else. Sessions the user opens from the Code tab do not pass it.
Environment
- Ubuntu 26.04 LTS (Hyper-V VM, Wayland/GNOME), x86_64
- claude-desktop 1.49585.0 from the Anthropic apt repository, Electron 44, bundled Claude Code 2.1.260
- Previous build on this machine: 1.40609.1, held since 2026-09-06 because of #92462; upgraded 2026-09-09 10:32 local time
- Target folder: a CIFS-mounted directory, not a git repository. Dispatch orchestrator runs locally (
dispatchParentOrigin: local)
Timeline (2026-09-09, local time)
10:28:30 [Stop hook] Query completed for session local_4c2ba47d-... <- blocker's last turn
10:32:42 apt upgrade: claude-desktop 1.40609.1 -> 1.49585.0
10:35:28 Stopping session local_4c2ba47d-...
10:35:30 Session local_4c2ba47d-... query iterator completed <- no query, not a blocker
10:36:2x app relaunched on the new build
10:43:05 start_code_task SUCCEEDS -> local_09c8d558-... created in the same folder
10:55:56 [CCD] LocalSessions.setFocusedSession: sessionId=local_4c2ba47d-... <- opened in the UI
10:55:56 [CCD] Warming session local_4c2ba47d-...
10:55:56 [CCD] Session local_4c2ba47d-... warmed successfully in 103ms <- CLI process re-attached
11:15:12 [error] [DispatchTools] start_code_task failed for <folder>: A Claude Code session (local_4c2ba47d-...) is already active in this directory.
11:18:34 same
11:20:40 same
The only event between the success at 10:43 and the first refusal at 11:15 is the UI focus at 10:55. Nothing was sent to local_4c2ba47d-...; it has been idle since 10:28.
Why idling does not release it
WarmLifecycle is initialized with arm=when-hidden:
10:36:22 [info] [WarmLifecycle:session] Initialized (arm=when-hidden)
10:36:22 [info] [WarmLifecycle:preview] Initialized (arm=when-hidden)
The 900s and 1800s idle timers only run while the session is hidden, so a session left open on screen keeps its query indefinitely and keeps the folder locked. Here the blocker had been idle for 47 minutes at the first refusal and 52 at the last.
Concurrency in the same folder already works
At the moment of the refusals, four sessions had that folder as cwd, two of them app-local children of the same Dispatch parent:
pid 3124359 10:43:05 local_09c8d558-... Dispatch child, started after the upgrade
pid 3132512 10:55:56 local_4c2ba47d-... the "blocker", warmed by UI focus
pid 2471685 Sep 8 21:39 remote-control session
pid 3151418 11:23:09 remote-control session
They coexist without conflict, so the refusal is not preventing a real collision. It only prevents Dispatch from adding one more.
Expected
Either of these would resolve it:
- Base the check on whether a session is actually busy (a turn in flight), not on whether a CLI process happens to be attached. A warmed but idle session should not hold a folder.
- Stop hardcoding
exclusiveCwd: trueon the Dispatch path, or make it configurable, so Dispatch matches what the Code tab already allows.
Two smaller points:
- The Dispatch tool set (
session_info,list_sessions,read_transcript,start_task,start_code_task,send_message,set_agent_name,list_code_workspaces,list_projects) has no archive or release tool, so the orchestrator cannot clear this state by itself. The error text says "already active" but does not say that closing or archiving the named session is the fix. - No changelog entry from 1.44121.1 through 1.49585.0 mentions this check, and the Dispatch guide still describes spawning many child tasks with no per-folder limit. The behaviour change in 1.49585.0 (the added
querycondition) is undocumented as well, so there is no way to tell from the release notes which builds carry which half of this.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Same on Windows 11 Pro (26200, MSIX), desktop 1.49585.0 / bundled CLI 2.1.266, with one more way the folder stays locked that I do not think is in this thread yet.
Sessions with Remote Control enabled are never idle-paused, hidden or not. The app logs
[CCD] Skipping pause for session <id> - remote control is active (startup-policy bridge)every 15 min for each of them. With "Enable remote control by default" ON (ccRemoteControlDefaultEnabled: true) that is every session opened from the Code tab, so each one keeps itsqueryfrom the moment it is opened until the user stops it or the app quits. On 10 Sept eight such sessions in one project folder were held from ~10:25 to ~23:00; on 11 Sept one from 09:40 to 18:25. Every Dispatchstart_code_taskinto that folder in those windows is refused. In the idle-pause path:let a=!i&&!!r.remoteControlEnabled, o=a&&this.rcPolicyBridgeYieldsOnScheduledRun(r); if(a&&!o){ ... Skipping pause ... return }.So for a user who keeps Remote Control on by default precisely in order to work from the phone, the folder is never free while the app is running, and the only entry point from the phone into that folder is refused for exactly as long as they are away. The 15-minute idle timer is not the practical bound; the Remote Control skip is. A scheduled-task run in the same folder adds its own lock for run + 15 min, and because scheduled sessions are excluded from Remote Control (#92276) the error for them comes back with no session id (
isVisibleToRemoteDispatchisdispatchParentOrigin !== "local"), so the orchestrator cannot route a follow-up to the blocker either.Refusals on this machine: 3 Sept 08:52/08:54/09:03, 5 Sept 07:44 (blocker: a session the app restored after its self-update at 07:39), 9 Sept 13:10 (blocker: a scheduled-task run spawned 13:09:55). Up to 25 Aug the same call succeeded in this folder with 8+ sessions alive in it (
Spawned host code session ... at <folder>). The Dispatch orchestrator's own transcript concluded the desktop was down; it was not. The only user-side mitigation I can see is turning Remote-Control-by-default off so sessions pause after 15 min hidden, which defeats the reason for having it on. +1 to basing the check on a turn in flight, or droppingexclusiveCwdon the Dispatch path.Also on macOS (Apple silicon), same symptom, three days running. Two datapoints I don't think are in the thread yet.
Archiving the blocking session from the Code tab does not release the folder. The error text, and the discussion around it, suggest that closing or archiving the named session is the fix. It is not. After archiving, start_code_task into the same folder kept returning "A Claude Code session (local_...) is already active in this directory", still naming the archived session. Only a full quit-and-reopen of the desktop app cleared it. That is consistent with the "or the app quits" in the Remote Control comment above: archiving appears to be UI state only and leaves the query attached.
start_task with a directory parameter is not affected. While start_code_task was refused for that folder, start_task with the same folder mounted started without complaint and could use git, run the full test suite and deploy. So exclusiveCwd: true really is enforced only on the code path, and this is a usable workaround for a blocked orchestrator, at the cost of the session not appearing in the Code tab.
From an orchestrator's point of view the practical problem is the one already raised here: there is no way to release the lock from the Dispatch tool set, and the only reliable remedy is an app restart, which the orchestrator cannot perform without terminating its own session. So the user has to be asked to do it manually, every time.
+1 to basing the check on a turn actually being in flight rather than on a CLI process being attached.
Remote access is a complete failure right now.
The whole point of Remote Control is to get into my computer from the phone and be sure I can actually do it. In practice, with existing sessions it's a lottery: every Claude Desktop update restarts the app, and all the sessions that were in remote mode end up disconnected. Great — you've left somewhere with just your phone, you're counting on connecting to your own computer, and nothing, because Claude updated itself.
Next, Dispatch. Dispatch exists exactly for this — to open a new session. And that's what I can't do. Now I simply can't.
I think the team could already start thinking about the feature that's actually needed.