Skip to content

Desktop broadcasts flood stderr while the main Renderer frame is unavailable #5135

Description

@me2seeks

What happened

While the Desktop main Renderer is being replaced after a reload, navigation, or renderer-process loss, main-process broadcasts can repeatedly print:

Error sending from webFrameMain: Error: Render frame was disposed before WebFrameMain could be accessed
    at WebFrameMain.send (node:electron/js2c/browser_init:2:107951)
    at WebContents.send (node:electron/js2c/browser_init:2:93999)

Session and transcript activity can turn the short unavailable-frame interval into a large stderr flood. The app remains alive because Electron logs the failure internally, but the useful main-process log is obscured.

safeSendToRenderer() currently treats a non-destroyed WebContents as sendable:

for (const contents of recipients) {
  if (!contents.isDestroyed()) contents.send(channel, ...args);
}

That predicate is insufficient: after render-process-gone, the same WebContents reports isDestroyed() === false while its main frame can already be disposed.

Expected behavior: broadcasts should not attempt delivery to a renderer generation that has no live main frame, and renderer recovery should not flood stderr. Events that require resynchronization should still be restored by the existing recovery path once the new renderer is ready.

How to reproduce

Product trigger (timing-dependent):

  1. Run Desktop from source with an active Session so Runtime Host/session events continue to be published.
  2. Reload the main Renderer or trigger renderer-process recovery while events are being published.
  3. Observe repeated Error sending from webFrameMain entries in the main-process output.

Deterministic Electron 43.4.1 verification:

  1. Create a hidden BrowserWindow and load a page.
  2. Continuously call window.webContents.send(...).
  3. Call window.webContents.forcefullyCrashRenderer(), await render-process-gone, and keep sending until a replacement page has loaded.
  4. The exact error above is printed repeatedly even though window.webContents.isDestroyed() is false.

The deterministic run made 9,989 send attempts and reproduced the error flood. Wrapping each webContents.send() call in application-side try/catch caught zero errors: Electron logs these failures internally, so a catch-only change does not address this reproduction.

Environment

  • Maka commit: a9b4f21afb17e0ef310d076382e69ddda3a441d7
  • Electron: 43.4.1
  • Original observation: Windows source checkout, Desktop, npm run dev
  • Deterministic verification: Linux x86_64 (7.0.0-30-generic), Desktop under Xvfb
  • Node.js: v26.3.0

Logs, screenshots, or additional context

Relevant current-main boundary: apps/desktop/src/main/main-window.ts:133-138.

Known callers include Session/local-session and browser-state broadcasts. The recovery path observes render-process-gone and may reload the same main BrowserWindow, so WebContents lifetime is not the same as renderer-frame/process lifetime.

This issue is limited to broadcast behavior during the unavailable renderer interval. The cause of any particular renderer crash/reload is separate.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions