Skip to content

Cowork VM doesn't start on named profiles: the VM service resolves the bundle path from the user-data-dir basename #5

Description

@rlacroce-rdi

--user-data-dir isolates Electron, but not the Cowork VM. Named profiles work fine for chat, MCP and file tools — only the Linux sandbox never boots.

Claude desktop 1.24012.9 (MSIX), ai-multi-instance v1.1.0, Windows 11. The README shows v1.9255.2.0, which predates the VM, so this is probably new ground.

What the log shows

From <profile>\logs\cowork_vm_node.log — note the two different paths:

[VM:start] Beginning startup, bundlePath=C:\devLR\_AI_multi_instance\ClaudeProfiles\<profile>\vm_bundles\claudevm.bundle
[VM:start] smol-bin.x64.vhdx copied successfully          <- Electron really writes there
[VM:start] Configuring Windows VM service...
[VM:start] Startup failed: failed to set VHDX path: VHDX file not found:
  C:\Users\Admin\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\<profile>\vm_bundles\claudevm.bundle\rootfs.vhdx

The segment after Roaming\ — normally Claude — is the basename of the user-data-dir. CoworkVMService (LocalSystem, machine-wide, app\resources\cowork-svc.exe) seems to get only that basename and rebuild %APPDATA%\<basename>\vm_bundles\claudevm.bundle in its own MSIX context. Electron writes to the profile folder, the service looks under AppData.

rootfs.vhdx is present and healthy (8 GB) in the profile bundle.

Two things that cost me time

Stale VMs block everything. The compute system survives app shutdown, so the next launch dies earlier with HRESULT 0x8037010f (HCS_E_SYSTEM_ALREADY_EXISTS) and masks the real error. With all instances closed, elevated:

Restart-Service CoworkVMService -Force
(Get-ChildItem \\.\pipe\).Name | Where-Object { $_ -match 'cowork' }
# only cowork-vm-service should remain

Junctions are refused by design, so redirecting vm_bundles is out:

configure: path ...\vm_bundles is a symlink or junction, refusing to open

Possible direction

If the basename theory holds, a user-data-dir that is a direct child of ...LocalCache\Roaming would make both sides compute the same path — no links, no duplicate bundle. Not expressible today, since engine.py does:

PROFILES_DIR = PROJECT_DIR / "ClaudeProfiles"

and the intermediate directory gets discarded anyway. A per-app override for the profile data dir would be enough to test it.

I tried this manually with --user-data-dir=<Roaming>\test-vm but called the result too early — Bundle:status: rootfs.vhdx missing turned out to be a transient state during bundle refresh, not a failure. So: a lead, not a verified fix.

Open question

Can two VMs coexist at all, or is one-at-a-time the ceiling? The tell is the daemon pipe suffix — if a second profile gets a different cowork-daemon-console-cowork-vm-XXXX there's hope; if it reuses the same one, the compute system ID is machine-wide.

Thanks for the tool — the --user-data-dir / CODEX_ELECTRON_USER_DATA_PATH writeups saved me a lot of digging.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions