anthropics / anthropics/claude-code

Windows MSIX: stealth auto-update leaves app unlaunchable with 0x80070020 until reboot (non-PTY children keep the AppX container and Helium User.dat hive mounted)

Đang mở
#92,167 2 bình luận 0 reaction 0 người được giao Xem trên GitHub
area:desktop duplicate platform:windows
Ngôn ngữ chính
Python
Star
145k
Fork
23.1k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

## Summary

A stealth (idle-timeout) auto-update of the MSIX-packaged Windows desktop app can leave the app permanently unlaunchable until a reboot. Every launch fails with `0x80070020` (`ERROR_SHARING_VIOLATION`).

Root cause: `beforeQuitForUpdate` only kills PTY process trees. Non-PTY child processes spawned by `claude.exe` (node, cmd, powershell, ssh, MCP servers) inherit the package identity and stay inside the Desktop AppX container. As long as one survives, the container is never destroyed, so the app-silo registry hive `…\SystemAppData\Helium\User.dat` stays mounted at `\REGISTRY\WC\Silouser_sid`. The newly registered package version then creates a *new* container and calls `RegLoadKey` on the *same* `User.dat` file, which fails with a sharing violation.

## Environment

- Windows 11 Pro 10.0.26200
- Claude desktop app, MSIX (`Claude_pzs8sxrjxfjjc`), Developer signature kind
- Version at failure: upgrading `1.44121.4.0` -> `1.46388.2.0`
- Packaged service present: `CoworkVMService` (`app\resources\cowork-svc.exe`, LocalSystem, auto-start)

## Symptoms

- App does not start. Windows shows a "file is in use by another program" style error.
- No `Claude.exe` processes are running.
- `Microsoft-Windows-AppModel-Runtime/Admin`:
- Event 215: `0x80070020: cannot create Desktop AppX container for package Claude_1.46388.2.0_x64__pzs8sxrjxfjjc`
- Event 208: `0x80070020: cannot create process for package Claude_1.46388.2.0_x64__pzs8sxrjxfjjc [LaunchProcess]`
- Process Monitor shows `RegLoadKey` / `CreateFile` on
`C:\Users\\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\SystemAppData\Helium\User.dat`
returning `SHARING VIOLATION`, issued by `svchost.exe` (Appinfo service) — the victim, not the holder.
- The hive remains listed in `HKLM\SYSTEM\CurrentControlSet\Control\hivelist` under `\REGISTRY\WC\Silouser_sid`.

## Timeline from the logs (single reproduction, times local)

1. `16:33:33` boot. `1.44121.4.0` running: `cowork-svc.exe` in container A, `claude.exe` (Electron main) in container B.
2. `16:35:32` AppXDeploymentServer event 400: `1.46388.2.0` staged successfully. Event 658: *"Marking package for deferred registration because 1.44121.4.0 is still running"*. Event 638 lists running app `Claude_pzs8sxrjxfjjc!Claude`.
3. `18:40:37` app main.log:
```
[stealth-update] Triggering stealth update after idle timeout
[stealth-relaunch] Saved z-order anchor / navigation history
[CCD] Killing 4 PTY process tree(s) on quit
```
4. `18:40:38` main.log: `beforeQuitForUpdate handler fired, going down for update`.
AppXDeploymentServer event 603: `RegisterByPackageFamilyName`, options `ForceApplicationShutdownOption`.
5. `18:41:09` AppModel-Runtime event 217 removes container A (the packaged service's container). **Container B — the `claude.exe` container of the old version — is never removed.** First 215/208 `0x80070020` fires in the same second. The stealth relaunch never completes; main.log has no further entries until after the reboot.
6. `18:41`–`19:14` 71 further 215/208 events across manual launches and Windows' own `RepairAppRegistrationOption` re-registrations. Each re-registration terminates `CoworkVMService` successfully (events 9648/9650, result `0x0`) and the launch still fails — the service is not the holder.
7. `19:15:28` on shutdown, event 217 finally removes container B for `1.44121.4.0`, 2 h 41 min after the app "quit".
8. `19:16:11` boot. App launches normally.

## Why the obvious diagnostics mislead

- `handle.exe` finds no open handle on `User.dat`. A silo-mounted hive is a kernel `CmLoadKey` reference on the silo object, not a user-mode file handle, so absence of handles proves nothing.
- Stopping `CoworkVMService` does not help, and the deployment stack already terminates it during repair registration (result `0x0`) while launches keep failing.
- `NtUnloadKey` on the silo path returns `C000003B` (`STATUS_OBJECT_PATH_SYNTAX_BAD`) — a path-syntax error, not evidence of a lock.

## Confirmation that non-PTY children stay in the container

In a healthy session, the app container holds these descendants of `claude.exe`, none of which are PTY trees:

```
node.exe <- cmd.exe <- claude.exe <- claude.exe (main)
node.exe <- cmd.exe <- node.exe <- cmd.exe <- claude.exe <- claude.exe (main)
powershell.exe <- claude.exe <- claude.exe (main)
conhost.exe <- claude.exe <- claude.exe (main)
```

Any of these outliving `beforeQuitForUpdate` keeps the Desktop AppX container, and therefore the hive, alive.

## Steps to reproduce

1. Run the packaged app; let it spawn a long-lived child process that is not part of a PTY tree (an SSH connection, an MCP server, a detached background shell).
2. Let the auto-updater stage a newer version while the app is running, so registration is deferred (event 658).
3. Leave the app idle until the stealth update fires; it quits and force-registers the new version.
4. Launch the app. It fails with `0x80070020` and keeps failing until a reboot.

## Impact

The app is unusable until reboot. No user-mode remedy exists: repair-registration, stopping the packaged service, and manual hive unloading all fail. The failure window is invisible to the user until they try to launch.

## Suggested fixes

- On `beforeQuitForUpdate`, terminate the whole package process tree, not just PTY trees — or wait for the Desktop AppX container to be torn down (poll for AppModel-Runtime event 217 / container destruction) before triggering registration.
- Before the stealth relaunch, verify that no processes remain in the package container; if any do, defer the update to the next opportunity instead of force-registering.
- Detect `0x80070020` on launch and surface an actionable message ("restart Windows to finish the update") instead of a generic file-in-use error.

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Hướng nghiên cứu

Start at the beforeQuitForUpdate handler and the stealth-relaunch path described in main.log; inspect how process cleanup handles non-PTY descendants of claude.exe. Reproduce with a long-lived child and check AppModel-Runtime events and User.dat sharing violations. Done means the update does not leave the AppX container or hive mounted and the new version launches without a reboot.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
electron, node.js, powershell
Lĩnh vực
desktop, operating-systems, release
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
45/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.