[BUG] Windows ARM64 desktop app keeps spawning cached x64 CLI (0xC0000005 under Prism); locked binary makes arch swap fail silently
Summary
On Windows ARM64 (Snapdragon), the desktop app's CLI preflight only checks for a .verified marker — it never validates the cached binary's architecture. After upgrading from the x64 desktop app to the native ARM64 build, the app silently keeps spawning the previously cached win32-x64 Bun CLI under Prism emulation, which crashes intermittently with 0xC0000005 (STATUS_ACCESS_VIOLATION). When the app does attempt to reinstall, the swap fails silently because the running x64 CLI locks claude.exe, leaving a .zst.partial and a resume-retry loop that never completes.
The result for the user: "Claude Code process exited with code 3221225477" randomly on session start/resume, persisting even after installing the correct ARM64 app.
Environment
- Device: Microsoft Surface Laptop, 7th Edition (Snapdragon, ARM64)
- OS: Windows 11 Pro, build 26200 (25H2)
- Desktop app: 1.20186.0 — initially x64 build, later replaced with native ARM64 (MSIX
Claude_1.20186.0.0_arm64) - CLI: 2.1.205 at
%APPDATA%\Claude\claude-code\2.1.205\claude.exe win32-arm64is present in the 2.1.205 release manifest, so a native binary was available the whole time
Timeline / evidence (from %APPDATA%\Claude\logs\main.log)
- With the x64 app installed (worst case — everything emulated): intermittent
0xC0000005since 2026-07-08, across CLI 2.1.202 and 2.1.205 and app 1.19367.0 → 1.20186.0. Crashes hit both session resume and bare "temporary query" startup (Failed to get commands from temporary query), i.e. not content-related. ARADAR_PRE_LEAK_64WER event was also recorded against claude.exe. No crash dumps are ever produced — the Bun panic handler swallows the exception, so WERLocalDumpsnever fires and the only artifact is the exit code.
- After installing the native ARM64 desktop app: crashes continue identically, because the app still spawns the cached x64 CLI:
2026-07-10 16:38:34 [info] Using Claude Code binary at: C:\Users\...\AppData\Roaming\Claude\claude-code\2.1.205\claude.exe <- PE machine type 0x8664 (x64)
2026-07-10 16:38:46 [error] Session ... query error: Claude Code process exited with code 3221225477
- The app then re-downloads (correctly sized for a different platform: 57,260,419 bytes vs the original x64 59,562,945), but cannot install it while any claude.exe is alive — the target file is locked. It silently loops:
2026-07-10 16:46:20 [info] [CCD] Downloaded 57260419 bytes
2026-07-10 16:46:21 [info] [CCD] Downloaded 57260419 bytes (resumed from 57260419)
2026-07-10 16:46:23 [info] [CCD] Downloaded 57260419 bytes (resumed from 57260419)
...
leaving download.<hash>.zst.partial next to the stale x64 claude.exe + .verified. No user-visible error; preflight keeps accepting the x64 binary because .verified exists:
2026-07-08 11:14:02 [info] [CCD] Binary preflight: .verified missing but download in flight — awaiting
Workaround that fixed it
- Delete
%APPDATA%\Claude\claude-code\<version>\.verified - Fully quit the app (tray → Quit) so nothing holds a lock on
claude.exe - Relaunch — the ARM64 app now downloads and installs the
win32-arm64binary (confirmed via PE header: machine0xAA64)
All crashes stopped once the CLI was native.
Suggested fixes
- Binary preflight should compare the cached binary's PE machine type against
process.arch(or record the platform key in.verified) and treat an architecture mismatch as "not installed". This mirrors the macOS-flavored reports in #13617 / #22117 where an x86_64 binary ends up running under translation on ARM hardware. - The installer should handle the locked-target case explicitly (staged install + swap on next start, and/or surface an error) instead of silently retry-looping on the completed download.
- Consider having the x64 desktop installer warn on ARM64 hosts (
IsWow64Process2reports the machine correctly even under emulation) — running the whole stack under Prism is what exposes the Bun JIT0xC0000005crashes in the first place.
🤖 Generated with Claude Code