Add comprehensive error handling and recovery UI #173

Merged
talksik merged 11 commits from claude/electron-error-handling-tPCJO into master 2026-04-21 02:22:02 +00:00
2 changed files with 59 additions and 37 deletions
Showing only changes of commit ed84b29c6b - Show all commits
+18 -5
View File
@@ -1,14 +1,15 @@
import * as Sentry from "@sentry/electron/renderer"; import * as Sentry from "@sentry/electron/renderer";
import { appConfig } from "@/config/env"; import { appConfig } from "@/config/env";
import { installErrorSinks } from "@/lib/errors"; import { installErrorSinks, reportError } from "@/lib/errors";
/** /**
* Initialise Sentry for a renderer process. No-ops when `sentryDsn` is empty * Initialise renderer error handling. When a DSN is configured, Sentry's
* so dev builds and unconfigured envs stay quiet. * own global handlers capture uncaught exceptions and unhandled promise
* rejections. Otherwise we install a minimal fallback so stray rejections
* aren't silent in dev / unconfigured envs.
*/ */
export function initSentryRenderer(): void { export function initSentryRenderer(): void {
if (!appConfig.sentryDsn) return; if (appConfig.sentryDsn) {
Sentry.init({ Sentry.init({
dsn: appConfig.sentryDsn, dsn: appConfig.sentryDsn,
tracesSampleRate: 0, tracesSampleRate: 0,
@@ -25,4 +26,16 @@ export function initSentryRenderer(): void {
data: context, data: context,
}), }),
}); });
return;
} }
window.addEventListener("unhandledrejection", (event) => {
reportError(event.reason, { scope: "unhandledrejection" });
});
window.addEventListener("error", (event) => {
reportError(event.error ?? new Error(event.message), {
scope: "window.error",
});
});
}
+14 -5
View File
@@ -1,15 +1,15 @@
import { app } from "electron"; import { app } from "electron";
import * as Sentry from "@sentry/electron/main"; import * as Sentry from "@sentry/electron/main";
import { appConfig } from "@/config/env"; import { appConfig } from "@/config/env";
import { installErrorSinks } from "@/lib/errors"; import { installErrorSinks, reportError } from "@/lib/errors";
/** /**
* Initialise Sentry for the main process. Captures uncaught exceptions from * Initialise main-process error handling. Sentry owns uncaught-exception
* the Node side and the crash reporter. Safe to call before `app.whenReady`. * capture when a DSN is configured; otherwise we install a minimal Node
* fallback so rejections aren't silent. Safe to call before `app.whenReady`.
*/ */
export function initSentryMain(): void { export function initSentryMain(): void {
if (!appConfig.sentryDsn) return; if (appConfig.sentryDsn) {
Sentry.init({ Sentry.init({
dsn: appConfig.sentryDsn, dsn: appConfig.sentryDsn,
tracesSampleRate: 0, tracesSampleRate: 0,
@@ -27,4 +27,13 @@ export function initSentryMain(): void {
data: context, data: context,
}), }),
}); });
return;
}
process.on("uncaughtException", (err) => {
reportError(err, { scope: "uncaughtException" });
});
process.on("unhandledRejection", (reason) => {
reportError(reason, { scope: "unhandledRejection" });
});
} }