Skip to content

[v3][Windows] WebView2 ProcessFailed is unhandled — browser-process death leaves the window permanently blank until app restart #5733

Description

@randalmurphal

Description

Wails v3 on Windows never registers WebView2's ProcessFailed event. When the WebView2 browser process dies — for any reason — the controller is left in a permanently invalid state: every subsequent COM call returns ERROR_INVALID_STATE (0x8007139F), the window renders blank, and only restarting the host app recovers. The app process itself stays alive, so the user is left staring at a dead white/blank window with no indication of what happened.

Concrete triggers:

Renderer-level failures (RENDER_PROCESS_EXITED / RENDER_PROCESS_UNRESPONSIVE) similarly leave a dead view where a simple re-navigation would recover.

Observable aftermath in a host log once the browser process is gone (every focus/resize event storms these):

[WebView2] Focus failed: The group or resource is not in the correct state to perform the requested operation.
[WebView2] SetSize failed: The group or resource is not in the correct state to perform the requested operation.

This is closely related to #5580's audit (transient COM errors exiting the process via errorCallback): alpha2.112 stopped the crash, but what remains is a window that can never recover. Handling ProcessFailed is the recovery half of that story.

Fix, validated

Branch: https://github.com/randalmurphal/wails/tree/fix/webview2-process-failed-recovery (single commit off the v3.0.0-alpha2.112 tag).

  • Register chromium.ProcessFailedCallback in setupChromium.
  • RENDER_PROCESS_EXITED / RENDER_PROCESS_UNRESPONSIVE → re-navigate to the last host-set URL (tracked in setURL; the dead webview can't be queried for it).
  • BROWSER_PROCESS_EXITED → rebuild: fresh edge.NewChromium(), re-run setupChromium, re-navigate. The old instance is abandoned rather than re-embedded — after a browser-process exit all its COM references dangle, and Embed's init-wait loop keys on a per-instance flag a used instance has already set, so re-embedding would return before a new controller exists.
  • GPU/utility process failures are deliberately left alone: Chromium restarts those itself, and if it gives up, that arrives as BROWSER_PROCESS_EXITED.
  • Work is deferred out of the callback via InvokeAsync, per WebView2 guidance about not calling controller methods reentrantly from event handlers.

Validated on Windows 11 26200 / WebView2 149.0.4022.98: with the browser process dying mid-session, the window rebuilds and re-renders in ~1–2s instead of staying blank.

Design points where you may want something different — happy to adjust in a PR:

  • In-page state is lost on rebuild (it's gone regardless; the question is whether recovery should be automatic).
  • Auto-reload on RENDER_PROCESS_UNRESPONSIVE is opinionated — some apps may prefer waiting out a transient hang, so that case may want to be option-gated or surfaced as an event.
  • There's currently no event surfaced to the app that a recovery happened; apps with meaningful frontend state may want a hook.

Happy to submit the branch as a PR if the approach looks right.

Environment

  • Wails: v3.0.0-alpha2.112 (tagged)
  • OS: Windows 11 Enterprise 25H2 (build 26200)
  • WebView2 Runtime: 149.0.4022.98

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions