Skip to content

(main): log uncaught exceptions and unhandled rejections in the main process, and tell the user #896

Open

Description

@devsuitup

Problem

  • Measured (main 2fb1779). No process.on('uncaughtException') or process.on('unhandledRejection') exists in any production file: the only hits are in test/ (and scripts/test-pr.js, a dev script). main.js uses electron-log (main.js:10, levels at main.js:35-36) but never calls log.errorHandler.startCatching() or an equivalent.
  • Measured. The path is real: (pty): a failed write to a Windows PTY input raises an uncaught main-process exception #517 (closed) was a failed ConPTY input write that surfaced as an uncaught main-process exception; test/pty-input-errors*.test.js and the trigger-watcher backstop tests guard individual sites, not the process.
  • Assumed (Electron default, not re-measured on Electron 41). An uncaught exception in main opens Electron's own "A JavaScript error occurred in the main process" dialog and is not written to main.log; an unhandled rejection is printed to stderr only. In a packaged build neither reaches the log the user can attach to a report.

Scope

  • One module (e.g. main-error-handlers.js, testable without Electron) that installs both handlers, registered in main.js before app.whenReady() (main.js:3782).
  • Each event: log.error with the stack and a short origin tag; then, once a window exists, one B8 error notice (public/app-notices.js) that says what happened and that details are in the log (Settings → Diagnostics). Rate-limit identical notices (same message within e.g. 60 s → one notice).
  • Decide and document the policy: keep running after a logged exception (today's de-facto behaviour behind the dialog) — no automatic quit.
  • Context note in .ai/contexts/ipc-bridge.md (or a new short context), CHANGELOG ### Changed entry.

Out of scope

  • Fixing the individual throw sites that the handler will start to reveal (separate issues, one per cause).
  • Renderer-side window.onerror / unhandledrejection (separate issue if wanted).
  • Crash reporting to a remote service.

Acceptance

  • Red first: a unit test that installs the handlers with an injected logger and notifier, emits process.emit('unhandledRejection', new Error('x'), Promise.resolve()) and process.emit('uncaughtException', new Error('y')), and asserts one log.error each with the stack and one notice each. Fails today (module absent).
  • A second identical error inside the rate window produces a log line but no second notice.
  • A handler whose logger throws does not throw (same guard as safeLogError in the trigger watcher).
  • task check green; Node 20/22 in CI (the test must not wait on unref timers only).

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions