Bug Report: Linux sandbox fails to start on Windows 10 (RPC pipe closed) — MSIX identity detection bug

Status Open
Reported on v2.1.247
Maintainer reply None cached
Activity 2 comments · opened Aug 31, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Title

Claude Desktop 1.40609.0 on Windows 10 22H2: Linux sandbox never starts ("RPC pipe closed") because the app reads package identity via WinRT Package::Current() (returns empty) while the process does have a valid MSIX package identity.

Environment

  • OS: Windows 10 Pro, build 19045 (22H2)
  • Claude Desktop version: 1.40609.0 (MSIX, installed via Store)
  • Package full name: Claude_1.40609.0.0_x64__pzs8sxrjxfjjc
  • Package family name: Claude_pzs8sxrjxfjjc
  • WSL: 2.7.12 (but the sandbox is not a WSL distro — LxssManager stays Stopped, which is expected)
  • CLI binary downloaded by the app: claude-code 2.1.247 (253 MB standalone exe)

Symptom

Any attempt to run a shell command in the sandbox fails immediately with:

Workspace unavailable. The isolated Linux environment failed to start (RPC pipe closed)
Failed to start Claude's workspace / RPC pipe closed

This has reproduced since first install (2026-08-30 14:52) and across multiple full reboots. The VM image is fully downloaded (rootfs.vhdx ~7.9 GB present), the package registration status is Ok, and all virtualization features (Subsystem-Linux / VirtualMachinePlatform / Hyper-V-Hypervisor) are Enabled. Re-registering the package and reinstalling do not help.

Root cause (two compounding bugs)

Bug 1 — the app reads package identity through the wrong API and gets empty

In main.log, every msix_identity_source is native_empty (54 occurrences, zero exceptions), and each MsixSpawnDiag session starts with identity_source=native_empty.

From unpacking app.asar, the identity lookup is:

function tOt() {
if (QDt) return gD;
if (QDt = true, Br()) {
try {
let e = (eOt ?? require("@ant/claude-native")).getCurrentPackageFamilyName();
if ($Dt = e ? native_ok : native_empty, e) {
return gD = e, P.info([MSIX] Package family from native API: %s, e), gD
}
} catch {
$Dt = native_unavailable,
P.info([MSIX] Native API unavailable, falling back to exe path parsing)
}
return gD = Nce(), gD ? P.info([MSIX] Package family from exe path: %s, gD) : P.warn([MSIX] Could not determine package family name), gD
}
...
}

So the native binding @ant/claude-native (claude-native-binding.node, Rust, built against the windows-0.58.0 crate) calls WinRT Package::Current(), and on this machine that returns an empty string without throwing — which is why native_empty is recorded and the exe-path fallback is never taken.

The decisive contrast (the "process has identity but the app can't read it" evidence):

  • Calling Win32 GetPackageFullName on the same running claude.exe process returns the correct identity: Claude_1.40609.0.0_x64__pzs8sxrjxfjjc (verified via Python ctypes against every live claude process).
  • The AppModel-Runtime/Admin event log shows the normal [LaunchProcess] + "process added to desktop AppX container for package Claude…" events.
  • In the same main.log, the exe-path-based fallback does resolve: [MSIX] Package family from exe path: Claude_pzs8sxrjxfjjc and [MSIX] Filesystem virtualization active — …\LocalCache\Roaming\Claude-3p exists.

So the process genuinely has a valid MSIX identity; only the WinRT Package::Current() path returns empty. On this Windows 10 build that API path is apparently unreliable (in a test harness, Package::Current() raises HRESULT 0x80073D54 "该进程没有程序包标识符" even for the packaged process).

Bug 2 — cowork-svc verifies the downloaded CLI child process, which has no package identity

cowork-svc.exe validates the pipe client using GetNamedPipeClientProcessId + GetPackageFamilyName. But when running a sandbox command, Claude spawns a separately downloaded CLI binary:

C:\Users\daixi\AppData\Local\Claude-3p\claude-code\2.1.247\claude.exe (cli_binary_source: 'required_version')

That exe lives outside the MSIX package and has no package identity, so cowork-svc sees client package: "", fails the signature/identity check, and closes the pipe → RPC pipe closed.

A related tell: the updater's identity check is also heuristic, not authoritative:

[updater] MSIX detected: windowsStore=false, appPathMatch=true, source=appPath,
exe=C:\Program Files\WindowsApps\Claude_...\app\claude.exe

i.e. it infers "is MSIX" from a path-string match, consistent with the native identity check being unreliable.

Impact / what I've already ruled out

  • Re-registering the package (Add-AppxPackage -DisableDevelopmentMode -Register), the in-app "Repair", a fresh user account, and full reinstalls all do not fix it (this matches a product bug, not a local-config problem).
  • No VMware/VirtualBox/emulator, no competing hypervisor, healthy vmcompute/HvHost/WSLService.
  • A hijacked Claude.lnk in the Start Menu (ACL containing a CodexSandboxUsers group, pointing directly at WindowsApps\...\claude.exe) was initially suspected and removed — it is a red herring, not the cause.

Requested fix

  1. Make the MSIX identity lookup fall back to Win32 GetPackageFullName (or treat an empty WinRT Package::Current() result as "unavailable" and take the exe-path/native fallback), rather than recording native_empty and giving up.
  2. Have cowork-svc verify the identity of the main app process (or otherwise account for the fact that the spawned CLI child process legitimately has no package identity), instead of rejecting the pipe client when its package family is empty.

Attachments I can provide on request

  • Full main.log with all msix_identity_source / MsixSpawnDiag lines (54 × native_empty).
  • cowork_vm_node.log showing the signature verification failed / client package: "" sequence leading to ERR_VM_PIPE_CLOSED.
  • Get-AppxPackage -Name *Claude* output (Status Ok, SignatureKind, InstallLocation).
  • The relevant decompiled app.asar snippet and the Win32 GetPackageFullName probe output proving the process does have identity.

What Should Happen?

Title

Claude Desktop 1.40609.0 on Windows 10 22H2: Linux sandbox never starts ("RPC pipe closed") because the app reads package identity via WinRT Package::Current() (returns empty) while the process does have a valid MSIX package identity.

Environment

  • OS: Windows 10 Pro, build 19045 (22H2)
  • Claude Desktop version: 1.40609.0 (MSIX, installed via Store)
  • Package full name: Claude_1.40609.0.0_x64__pzs8sxrjxfjjc
  • Package family name: Claude_pzs8sxrjxfjjc
  • WSL: 2.7.12 (but the sandbox is not a WSL distro — LxssManager stays Stopped, which is expected)
  • CLI binary downloaded by the app: claude-code 2.1.247 (253 MB standalone exe)

Symptom

Any attempt to run a shell command in the sandbox fails immediately with:

Workspace unavailable. The isolated Linux environment failed to start (RPC pipe closed)
Failed to start Claude's workspace / RPC pipe closed

This has reproduced since first install (2026-08-30 14:52) and across multiple full reboots. The VM image is fully downloaded (rootfs.vhdx ~7.9 GB present), the package registration status is Ok, and all virtualization features (Subsystem-Linux / VirtualMachinePlatform / Hyper-V-Hypervisor) are Enabled. Re-registering the package and reinstalling do not help.

Root cause (two compounding bugs)

Bug 1 — the app reads package identity through the wrong API and gets empty

In main.log, every msix_identity_source is native_empty (54 occurrences, zero exceptions), and each MsixSpawnDiag session starts with identity_source=native_empty.

From unpacking app.asar, the identity lookup is:

function tOt() {
if (QDt) return gD;
if (QDt = true, Br()) {
try {
let e = (eOt ?? require("@ant/claude-native")).getCurrentPackageFamilyName();
if ($Dt = e ? native_ok : native_empty, e) {
return gD = e, P.info([MSIX] Package family from native API: %s, e), gD
}
} catch {
$Dt = native_unavailable,
P.info([MSIX] Native API unavailable, falling back to exe path parsing)
}
return gD = Nce(), gD ? P.info([MSIX] Package family from exe path: %s, gD) : P.warn([MSIX] Could not determine package family name), gD
}
...
}

So the native binding @ant/claude-native (claude-native-binding.node, Rust, built against the windows-0.58.0 crate) calls WinRT Package::Current(), and on this machine that returns an empty string without throwing — which is why native_empty is recorded and the exe-path fallback is never taken.

The decisive contrast (the "process has identity but the app can't read it" evidence):

  • Calling Win32 GetPackageFullName on the same running claude.exe process returns the correct identity: Claude_1.40609.0.0_x64__pzs8sxrjxfjjc (verified via Python ctypes against every live claude process).
  • The AppModel-Runtime/Admin event log shows the normal [LaunchProcess] + "process added to desktop AppX container for package Claude…" events.
  • In the same main.log, the exe-path-based fallback does resolve: [MSIX] Package family from exe path: Claude_pzs8sxrjxfjjc and [MSIX] Filesystem virtualization active — …\LocalCache\Roaming\Claude-3p exists.

So the process genuinely has a valid MSIX identity; only the WinRT Package::Current() path returns empty. On this Windows 10 build that API path is apparently unreliable (in a test harness, Package::Current() raises HRESULT 0x80073D54 "该进程没有程序包标识符" even for the packaged process).

Bug 2 — cowork-svc verifies the downloaded CLI child process, which has no package identity

cowork-svc.exe validates the pipe client using GetNamedPipeClientProcessId + GetPackageFamilyName. But when running a sandbox command, Claude spawns a separately downloaded CLI binary:

C:\Users\daixi\AppData\Local\Claude-3p\claude-code\2.1.247\claude.exe (cli_binary_source: 'required_version')

That exe lives outside the MSIX package and has no package identity, so cowork-svc sees client package: "", fails the signature/identity check, and closes the pipe → RPC pipe closed.

A related tell: the updater's identity check is also heuristic, not authoritative:

[updater] MSIX detected: windowsStore=false, appPathMatch=true, source=appPath,
exe=C:\Program Files\WindowsApps\Claude_...\app\claude.exe

i.e. it infers "is MSIX" from a path-string match, consistent with the native identity check being unreliable.

Impact / what I've already ruled out

  • Re-registering the package (Add-AppxPackage -DisableDevelopmentMode -Register), the in-app "Repair", a fresh user account, and full reinstalls all do not fix it (this matches a product bug, not a local-config problem).
  • No VMware/VirtualBox/emulator, no competing hypervisor, healthy vmcompute/HvHost/WSLService.
  • A hijacked Claude.lnk in the Start Menu (ACL containing a CodexSandboxUsers group, pointing directly at WindowsApps\...\claude.exe) was initially suspected and removed — it is a red herring, not the cause.

Requested fix

  1. Make the MSIX identity lookup fall back to Win32 GetPackageFullName (or treat an empty WinRT Package::Current() result as "unavailable" and take the exe-path/native fallback), rather than recording native_empty and giving up.
  2. Have cowork-svc verify the identity of the main app process (or otherwise account for the fact that the spawned CLI child process legitimately has no package identity), instead of rejecting the pipe client when its package family is empty.

Attachments I can provide on request

  • Full main.log with all msix_identity_source / MsixSpawnDiag lines (54 × native_empty).
  • cowork_vm_node.log showing the signature verification failed / client package: "" sequence leading to ERR_VM_PIPE_CLOSED.
  • Get-AppxPackage -Name *Claude* output (Status Ok, SignatureKind, InstallLocation).
  • The relevant decompiled app.asar snippet and the Win32 GetPackageFullName probe output proving the process does have identity.

Error Messages/Logs

Steps to Reproduce

Title

Claude Desktop 1.40609.0 on Windows 10 22H2: Linux sandbox never starts ("RPC pipe closed") because the app reads package identity via WinRT Package::Current() (returns empty) while the process does have a valid MSIX package identity.

Environment

  • OS: Windows 10 Pro, build 19045 (22H2)
  • Claude Desktop version: 1.40609.0 (MSIX, installed via Store)
  • Package full name: Claude_1.40609.0.0_x64__pzs8sxrjxfjjc
  • Package family name: Claude_pzs8sxrjxfjjc
  • WSL: 2.7.12 (but the sandbox is not a WSL distro — LxssManager stays Stopped, which is expected)
  • CLI binary downloaded by the app: claude-code 2.1.247 (253 MB standalone exe)

Symptom

Any attempt to run a shell command in the sandbox fails immediately with:

Workspace unavailable. The isolated Linux environment failed to start (RPC pipe closed)
Failed to start Claude's workspace / RPC pipe closed

This has reproduced since first install (2026-08-30 14:52) and across multiple full reboots. The VM image is fully downloaded (rootfs.vhdx ~7.9 GB present), the package registration status is Ok, and all virtualization features (Subsystem-Linux / VirtualMachinePlatform / Hyper-V-Hypervisor) are Enabled. Re-registering the package and reinstalling do not help.

Root cause (two compounding bugs)

Bug 1 — the app reads package identity through the wrong API and gets empty

In main.log, every msix_identity_source is native_empty (54 occurrences, zero exceptions), and each MsixSpawnDiag session starts with identity_source=native_empty.

From unpacking app.asar, the identity lookup is:

function tOt() {
if (QDt) return gD;
if (QDt = true, Br()) {
try {
let e = (eOt ?? require("@ant/claude-native")).getCurrentPackageFamilyName();
if ($Dt = e ? native_ok : native_empty, e) {
return gD = e, P.info([MSIX] Package family from native API: %s, e), gD
}
} catch {
$Dt = native_unavailable,
P.info([MSIX] Native API unavailable, falling back to exe path parsing)
}
return gD = Nce(), gD ? P.info([MSIX] Package family from exe path: %s, gD) : P.warn([MSIX] Could not determine package family name), gD
}
...
}

So the native binding @ant/claude-native (claude-native-binding.node, Rust, built against the windows-0.58.0 crate) calls WinRT Package::Current(), and on this machine that returns an empty string without throwing — which is why native_empty is recorded and the exe-path fallback is never taken.

The decisive contrast (the "process has identity but the app can't read it" evidence):

  • Calling Win32 GetPackageFullName on the same running claude.exe process returns the correct identity: Claude_1.40609.0.0_x64__pzs8sxrjxfjjc (verified via Python ctypes against every live claude process).
  • The AppModel-Runtime/Admin event log shows the normal [LaunchProcess] + "process added to desktop AppX container for package Claude…" events.
  • In the same main.log, the exe-path-based fallback does resolve: [MSIX] Package family from exe path: Claude_pzs8sxrjxfjjc and [MSIX] Filesystem virtualization active — …\LocalCache\Roaming\Claude-3p exists.

So the process genuinely has a valid MSIX identity; only the WinRT Package::Current() path returns empty. On this Windows 10 build that API path is apparently unreliable (in a test harness, Package::Current() raises HRESULT 0x80073D54 "该进程没有程序包标识符" even for the packaged process).

Bug 2 — cowork-svc verifies the downloaded CLI child process, which has no package identity

cowork-svc.exe validates the pipe client using GetNamedPipeClientProcessId + GetPackageFamilyName. But when running a sandbox command, Claude spawns a separately downloaded CLI binary:

C:\Users\daixi\AppData\Local\Claude-3p\claude-code\2.1.247\claude.exe (cli_binary_source: 'required_version')

That exe lives outside the MSIX package and has no package identity, so cowork-svc sees client package: "", fails the signature/identity check, and closes the pipe → RPC pipe closed.

A related tell: the updater's identity check is also heuristic, not authoritative:

[updater] MSIX detected: windowsStore=false, appPathMatch=true, source=appPath,
exe=C:\Program Files\WindowsApps\Claude_...\app\claude.exe

i.e. it infers "is MSIX" from a path-string match, consistent with the native identity check being unreliable.

Impact / what I've already ruled out

  • Re-registering the package (Add-AppxPackage -DisableDevelopmentMode -Register), the in-app "Repair", a fresh user account, and full reinstalls all do not fix it (this matches a product bug, not a local-config problem).
  • No VMware/VirtualBox/emulator, no competing hypervisor, healthy vmcompute/HvHost/WSLService.
  • A hijacked Claude.lnk in the Start Menu (ACL containing a CodexSandboxUsers group, pointing directly at WindowsApps\...\claude.exe) was initially suspected and removed — it is a red herring, not the cause.

Requested fix

  1. Make the MSIX identity lookup fall back to Win32 GetPackageFullName (or treat an empty WinRT Package::Current() result as "unavailable" and take the exe-path/native fallback), rather than recording native_empty and giving up.
  2. Have cowork-svc verify the identity of the main app process (or otherwise account for the fact that the spawned CLI child process legitimately has no package identity), instead of rejecting the pipe client when its package family is empty.

Attachments I can provide on request

  • Full main.log with all msix_identity_source / MsixSpawnDiag lines (54 × native_empty).
  • cowork_vm_node.log showing the signature verification failed / client package: "" sequence leading to ERR_VM_PIPE_CLOSED.
  • Get-AppxPackage -Name *Claude* output (Status Ok, SignatureKind, InstallLocation).
  • The relevant decompiled app.asar snippet and the Win32 GetPackageFullName probe output proving the process does have identity.

Claude Model

None

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.251 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗