[BUG] Dispatch cannot start a second Code session in the same folder since 1.44121.x: exclusiveCwd hardcoded true in startCodeSession
Summary
Since Claude Desktop 1.44121.x (Windows, MSIX), Dispatch can no longer start a second Code session in the same folder. The call fails with:
Failed to start code session: Another Claude Code session is already active in this directory.
This is a regression: the flag that triggers the check does not exist in any build up to and including 1.37937.3.0. It also contradicts the documented behaviour — Desktop application → Work in parallel with sessions states that multiple sessions can run in parallel and that Dispatch can start sessions for you.
Sessions started by hand in the app are unaffected. Only the Dispatch path is blocked.
Environment
- Windows 11 Pro, 26200
- Claude Desktop 1.44121.4.0 (MSIX, installed from claude.com)
- Working folder is not a git repository (so no worktree isolation is possible)
Steps to reproduce
- Have a folder that is not a git repo, with at least one non-archived Code session already in it.
- From Dispatch, ask to open a new Code session in that same folder.
- The call fails with the error above. Every further attempt fails until the existing session is archived.
Expected: a second parallel Code session in that folder, as documented.
Actual: CwdInUseError.
Root cause (from app/resources/app.asar)
The check is gated behind an exclusiveCwd option:
if (n?.exclusiveCwd) {
let t = this.findActiveSessionByCwd(f, r);
if (t) throw new Hu(e.cwd, ...) // CwdInUseError
}
exclusiveCwd appears exactly twice in the whole bundle: once where it is read (above), and once where it is set — hardcoded true in the Dispatch bridge:
startCodeSession: async (cwd, message, title, model) => {
...
return o.startSession(
{cwd, message, title, model, permissionMode},
{dispatchParentId, dispatchParentOrigin:"local",
origin:{kind:"auto-continuation"}, initiator:"dispatch",
exclusiveCwd:!0}
)
}
No other session-start path sets it, which matches the observed behaviour (manual sessions still work).
What counts as "in use" is any non-archived session with a matching cwd or originCwd:
for (let n of this.sessions.values())
if (!(n.isArchived || n.sessionId === t) && (
normalizeCwdKey(n.originCwd || n.cwd) === e ||
(n.originCwd && n.originCwd !== n.cwd && normalizeCwdKey(n.cwd) === e)
)) return n.sessionId
Because originCwd is compared too, a git worktree session would also match on its base repo path — so worktree isolation does not appear to exempt this path either.
When it appeared
grep for exclusiveCwd / CwdInUseError across the app.asar of every build still present on this machine:
| Build | Date | exclusiveCwd | CwdInUseError |
|---|---|---|---|
| 1.32885.1.0 | Aug 19 | 0 | 0 |
| 1.34493.0.0 | Aug 21 | 0 | 0 |
| 1.37937.0.0 | Aug 26 | 0 | 0 |
| 1.37937.1.0 | Aug 26 | 0 | 0 |
| 1.37937.3.0 | Aug 27 | 0 | 0 |
| 1.44121.4.0 | Sep 3 | 2 | 2 |
Deployment log on this machine: 1.40609.1.0 → 1.44121.2.0 (05:48) → 1.44121.4.0 (07:09), both on Sep 3. Dispatch could open parallel sessions in this folder the day before, on 1.40609.1.0.
Impact
For a non-git working folder this removes the only remote entry point into it:
- opening a Code session from the phone goes through a GitHub repo, so a non-git folder is not reachable that way;
- Dispatch was the remaining route, and it is now blocked;
- only a manual session at the keyboard still works.
Archiving is not a workable mitigation: it clears the folder only until the next session exists, and it cannot give two live parallel sessions at all, since the first one immediately blocks the second.
Suggested fix
Either drop exclusiveCwd:!0 from startCodeSession, or make it configurable, or scope the check to sessions that are actually running rather than to every non-archived session in the folder.
Note
The 1.44121.1 fix "sessions failing to start on Windows for accounts with many saved artifacts, scheduled tasks, or connected folders" was reverted in 1.44121.2 and is not restored in 1.44121.4, so that failure mode is also live again. That may be a separate issue, but it lands on the same users.
---
Investigated with Claude Code.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Follow-up with application-side logs, which I could not produce in the original report.
Correction to myself first: I initially concluded the app writes no logs since Aug 23. That was wrong — the log directory moved. It is no longer
%APPDATA%\Claude\logsbut%LOCALAPPDATA%\Claude\Logs, and the move happened during the1.32352.1.0 → 1.34493.1.0update. The seam is visible to the second:Logs are continuous since then. So issue #91640 ("app writes no logs") is not what I was seeing.
The failures, as the app records them
Seven refusals today, all on the Dispatch path:
Every entry is tagged
[DispatchTools] start_code_task— matching the code path whereexclusiveCwd:!0is hardcoded. Sessions opened by hand in the Code tab were never refused.Note the last one:
casper-sbsis a git repository, and it was refused just like the non-git folder. So worktree isolation does not exempt this path, which is consistent with the check comparingoriginCwdas well ascwd.First refusal came at 09:38 — about 2.5 hours after the update landed.
Update timeline from the app's own log
Two observations, secondary to this issue but worth recording:
RegisterByPackageFamilyName … ForceApplicationShutdownOptionafter Windows had twice refused withPackages were not updated because affected apps are still running. So two builds landed under an active user session within 80 minutes.check_interval_ticks=1 (default 4)— a remote flag shortened the update check interval right before the second update.So the version that introduced the behaviour reached this machine through two forced restarts in one morning, and the first user-visible symptom appeared 2.5 hours later.
Follow-up with a concrete repro of the failure mode: the directory is held by a stale session record, not by a live session.
Environment: Claude Desktop 1.44121.4.0 (MSIX), Windows 11, CLI 2.1.258.
What happened
start_code_task) refused every attempt to open a session inD:\...\sb-projectswithAnother Claude Code session is already active in this directory.%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\claude-code-sessions\<installId>\<accountId>\local_<uuid>.json— showed exactly one record withisArchived: falseand thatcwd, last active two days earlier. Its CLI process was long gone.Why this is worth fixing
findActiveSessionByCwd()treats "not archived" as "active". Liveness is actually known to the app: live CLI sessions are registered in~/.claude/sessions/<pid>.json, and the session object carriesquery. A dead-but-unarchived record blocks the directory forever, across restarts.exclusiveCwdis hardcodedtrueon the Dispatch start path only. Manual starts have no such check — and two sessions started manually in the same directory run happily side by side (measured: two live PIDs, same cwd). So the restriction is policy, not a technical constraint.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 delete tool.archive_sessionlives inccd_session_mgmt, available to code sessions only. So from a phone — where Dispatch is the only channel to the machine — the state is unrecoverable: the tool that could clear it can only run in a session that cannot be started because of it.Suggested fixes, in order of value
isArchived.Request: please allow Dispatch to open several sessions in one folder
Beyond the stale-record bug, the one-session-per-directory policy itself breaks my main workflow, and I would really like it reconsidered — or at least made configurable.
I work from my phone most of the time. Dispatch is my only channel to the machine. I do not remember the full structure of my local repo, so I cannot reliably name the exact target subfolder when asking Dispatch to start a session. What works for me is the obvious thing: Dispatch opens a session at the repo root, and then, inside the session, we navigate to whatever subfolder the task actually concerns.
That means several concurrent sessions at the same root — which is exactly what the current policy forbids. The suggested workaround (use different subfolders) does not help: naming the subfolder up front is the very thing I cannot do from a phone, and it also costs auto-memory and local-scope MCP, both of which are bound to the path.
Concretely, any of these would solve it for me:
Thanks for looking at this.
Same regression on macOS, same day, independently traced to the same check.
Environment: macOS 25.5.0, Claude.app 1.44121.4 (Electron 42.10.0), Claude Code desktop SDK 2.1.258. App bundle replaced 2026-09-03 01:51 local. Previous SDK 2.1.255 did not have this behavior.
Evidence it is a regression: on 2026-09-01 (pre-update) three Dispatch-spawned Code sessions in the same non-git folder ran concurrently for over an hour (
main.log:[DispatchTools] Spawned host code session … at <folder>at 08:23, 12:40, 13:11, with lifespans overlapping until 14:31). After the update, every Dispatch spawn into that folder fails:(12:15, 13:24, 13:50, 15:20 local.) Manual sessions from the Code tab in the same folder were never refused; three ran side by side while Dispatch was being refused.
Confirming the "stale record" finding: the check is
findActiveSessionByCwd, which walks every loaded session record and returns the first non-archived one whose cwd matches. It does not consultisRunningor~/.claude/sessions/<pid>.json. In my case the folder held 791 un-archived scheduled-task run sessions back to July 1 (these are hidden from Recents, #78229, and never auto-archived, #90251), so the user could see only 4 sessions and had no way to find or archive the blockers. After archiving those 791 on disk with the app quit, the spawn still failed on the 4 remaining idle chat sessions, so idle chats block too. A control spawn into a folder with zero session records succeeded immediately.Net: with the current check, Dispatch cannot target any folder the user has ever had a conversation in unless every session there is archived, and folders hosting scheduled tasks re-block on the next run. +1 to scoping the check to live sessions (the pid registry already exists) or dropping
exclusiveCwdfrom the Dispatch path.