Desktop app: webview unresponsive handler kills renderer when app is backgrounded by macOS
Bug Description
The Claude desktop app goes blank/crashes when the user switches away from it for a few minutes and then returns. The user has to close and reopen the app to recover.
Root Cause
Found in app.asar → .vite/build/index.js. The "unresponsive" event handler on the main webview unconditionally kills the renderer:
t.on("unresponsive", async () => {
$.info("Main webview is unresponsive, will kill and reload");
tj("Main webview became unresponsive", {level:"error", tags:{event:"webview-unresponsive"}});
U$++;
t.forcefullyCrashRenderer();
t.reload();
});
The problem: When the user switches to another app, macOS App Nap throttles/suspends the Electron renderer process. The main process detects the renderer as "unresponsive" (because it's napped, not because it's actually hung), and the handler immediately calls forcefullyCrashRenderer() + reload() — nuking the session.
Note: backgroundThrottling: false IS set in webPreferences, but this only controls Chromium's internal throttling of timers/rAF. It does not prevent macOS App Nap from suspending the entire renderer process.
Evidence from logs (~/Library/Logs/Claude/main.log)
7 crashes in a single session today (2026-04-15), all correlating with window focus changes:
14:09:52 [info] [SkillsPlugin] Window focused — polling now (last poll was 686855ms ago)
14:10:10 [info] Main webview is unresponsive, will kill and reload
14:10:10 [error] Sentry caught: { value: 'Main webview became unresponsive' }
14:28:49 [info] Main webview is unresponsive, will kill and reload
15:08:42 [info] Main webview is unresponsive, will kill and reload
15:14:21 [info] Main webview is unresponsive, will kill and reload
15:17:50 [info] Main webview is unresponsive, will kill and reload
15:22:35 [info] Main webview is unresponsive, will kill and reload
15:25:38 [info] Main webview is unresponsive, will kill and reload
The pattern is clear: user leaves → macOS naps the renderer → main process fires "unresponsive" → handler kills renderer → user returns to blank screen.
Suggested Fix
The "unresponsive" handler should:
- Check if the window is focused/visible before killing the renderer. If backgrounded, suppress the kill.
- Add a grace period: when the user returns (window gets focus), wait 5–10 seconds for the renderer to wake up before considering it truly unresponsive.
- Disable App Nap for the renderer process using Electron's
app.commandLine.appendSwitch('disable-renderer-backgrounding')or theNSSupportsAutomaticTermination/NSAppSleepDisabledInfo.plist keys.
Proposed pseudocode:
t.on("unresponsive", async () => {
// Don't kill the renderer if the window is backgrounded —
// macOS App Nap likely just suspended it
if (!t.isFocused() && !t.isVisible()) {
$.info("Webview unresponsive but window is backgrounded, skipping kill");
return;
}
// ...existing kill logic for genuinely hung renderers...
});
Environment
- Claude Desktop app (Electron)
- macOS (Apple Silicon - MacBook Air)
- Version: 2.1.38
- Logs:
~/Library/Logs/Claude/main.log
Reproduction
- Open Claude desktop app
- Start a conversation / agent session
- Switch to another app for 2-5 minutes
- Switch back to Claude → screen is blank/white, session is gone
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗