[BUG] Claude Desktop 1.20186.9.0 (Windows MSIX): unreachable preview URL causes >1GB/sec allocation that blocks the main process; watchdog reload re-triggers it in an infinite hang loop
TL;DR
If a preview card points at a dev server it can't actually reach, Claude Desktop doesn't show an error — it melts. The preview webview spins on "Loading…" and starts allocating over 1 GB/sec, which blocks the Electron main process and freezes the entire app. The watchdog then kills and reloads the webview — but the reload restores the same session, which re-embeds the same broken preview, which explodes again. Infinite hang/reload loop, getting faster each round, until you fully quit the app.
In my case the preview was unreachable because Vite on Windows bound to IPv6 ::1 only, so 127.0.0.1:<port> was connection-refused. That part is Vite's quirk, not Anthropic's bug. The bug is that an unreachable localhost port can take down the whole application. A dead port should render "couldn't connect", not a denial of service.
Preflight Checklist
- [x] I have searched existing issues
- [x] This is a single bug report
- [x] I am using the latest version
Environment
- App: Claude Desktop
1.20186.9.0, Windows 11, MSIX (Store),Claude_pzs8sxrjxfjjc - Machine: 64 GB RAM (33 GB free throughout — this was never system memory pressure)
Reproduction
- Start a dev server that is not reachable at the URL the preview embeds. I hit this naturally:
npm run dev -- --port 5221 --strictPort(Vite) bound to::1only on Windows. Verified:
http://127.0.0.1:5221→ connection refusedhttp://[::1]:5221→ HTTP 200
- Open the resulting preview card in a Claude Code-in-Desktop session (route
claude.ai/epitaxy/local_<uuid>). - Watch the app die.
Should also reproduce by pointing a preview at any dead localhost port.
Expected
Preview shows a connection error. Failure is contained to the preview.
Actual
The preview sits on "Loading…" forever while the renderer allocates unboundedly and pegs ~5 cores. Two separate renderer processes were caught at 16.4 GB (in ~50 s from spawn) and 21 GB working set before OOM-ing.
This blocks the main process — which is single-threaded and brokers all UI/IPC — so every window freezes. From logs\main.log, event-loop stalls double each round with main RSS tracking right alongside:
| Time | Main thread blocked | Main RSS |
|---|---|---|
| 14:33:18 | 564 ms | 808 MB |
| 14:33:24 | 1,997 ms | 1,538 MB |
| 14:33:33 | 5,223 ms | 2,710 MB |
| 14:34:02 | 19,419 ms | 6,007 MB |
| 14:34:46 | 43,227 ms | 8,961 MB |
| 14:37:17 | 151,279 ms | 4,340 MB |
Timing correlation is tight: the Vite server started at 14:33:10; the first stall hit at 14:33:18 — 8 seconds later.
The loop (the part I'd most like fixed)
[warn] [event-loop-stall] main process blocked for 19230ms ... rss 5229MB
[error] Sentry caught: { value: 'Main webview became unresponsive' }
[info] Main webview is unresponsive, will kill and reload
The watchdog reload restores the same session route → re-embeds the same broken preview → explodes again. Four episodes in ten minutes, accelerating: 14:33 → 14:38 → 14:42 → 14:43. There's no backoff and no circuit breaker, so the recovery mechanism is what makes it self-sustaining.
Main-process RSS also never returns to baseline across reloads (326 MB at launch → 10.8 GB); only a full app restart clears it.
Note the app's own [likely sleep: duration_heuristic] tag mis-attributes these stalls to the machine sleeping. It wasn't asleep — RSS was exploding.
Asks
- A failed preview load must not allocate unboundedly — cap it, and fail the load instead of retry-storming.
- Contain preview failures to the preview. A dead localhost port shouldn't be able to block the main process.
- Give the unresponsive-webview watchdog a circuit breaker, so it doesn't reload straight back into the state that just killed it.
Evidence
- Sentry event IDs (these are the exact stalls, already in your telemetry):
a75df8618ecb4ac5b28de574bb235270,5437750ebea444438b6fb9ad8449e19c - Logs + Crashpad dumps:
%LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\{logs,Crashpad}
Possibly related (same symptom, different trigger)
- #76725 — kill-and-reload loop on Windows MSIX, but triggered at cold start (Cowork warm-lifecycle), not by a preview.
- #75226 — main-process event loop repeatedly blocked.
If maintainers think this is the same underlying fragility as those, happy to have it folded in — but the trigger here is specific and reproducible on demand, which may make it the easiest of the three to chase down.
Minor, noticed while debugging (not worth separate reports)
MaxListenersExceededWarningon eIPC channels (claude.settings_$_AppPreferences_$_preferencesChanged,AutoUpdater.updaterState) — 11 listeners and climbing, accumulating on each webview reload. Probably compounds the leak the longer the loop runs.- Every line in
main.logis written twice (duplicate logger transport).