Desktop app: webview unresponsive handler kills renderer when app is backgrounded by macOS

Resolved 💬 2 comments Opened Apr 15, 2026 by EnterpriseEagle Closed Apr 18, 2026

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:

  1. Check if the window is focused/visible before killing the renderer. If backgrounded, suppress the kill.
  2. 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.
  3. Disable App Nap for the renderer process using Electron's app.commandLine.appendSwitch('disable-renderer-backgrounding') or the NSSupportsAutomaticTermination / NSAppSleepDisabled Info.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

  1. Open Claude desktop app
  2. Start a conversation / agent session
  3. Switch to another app for 2-5 minutes
  4. Switch back to Claude → screen is blank/white, session is gone

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗