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)

Abierto
#92,167 2 comentarios 0 reacciones 0 asignados Ver en GitHub
area:desktop duplicate platform:windows
Lenguaje dominante
Python
Estrellas
145k
Forks
23.1k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

## 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.

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
electron, node.js, powershell
Área
desktop, operating-systems, release
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Activo
Claridad
Bastante claro
Aptitud para principiantes
45/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.