diff --git a/src/main/index.ts b/src/main/index.ts index 5ee77fcf..6c674346 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -9,6 +9,17 @@ import { GitOperations } from "./git"; import { createMenu } from "./menu"; import Store from "electron-store"; +// Global error handlers to prevent crashes +process.on("uncaughtException", (error) => { + console.error("Uncaught Exception:", error); + // Don't call app.quit() here as it may cause issues during startup +}); + +process.on("unhandledRejection", (reason, promise) => { + console.error("Unhandled Rejection at:", promise, "reason:", reason); + // Don't call app.quit() here as it may cause issues during startup +}); + // Performance logging const APP_START = Date.now(); function perfLog(label: string, startTime?: number) { @@ -304,6 +315,13 @@ app.whenReady().then(async () => { ); app.quit(); } +}).catch((error) => { + console.error("App.whenReady() failed:", error); + dialog.showErrorBox( + "Startup Error", + `Failed to start application: ${(error as Error).message}\n\nStack: ${(error as Error).stack}`, + ); + app.quit(); }); app.on("window-all-closed", () => { @@ -321,7 +339,12 @@ app.on("before-quit", () => { // IPC Handlers ipcMain.handle("utils:fromBase64", (_event, data: string) => { - return Buffer.from(data, "base64").toString("utf8"); + try { + return Buffer.from(data, "base64").toString("utf8"); + } catch (error) { + console.error("Error in utils:fromBase64:", error); + throw error; + } }); ipcMain.handle("auth:login", async () => { @@ -353,6 +376,7 @@ ipcMain.handle( await gitOps.clone(repoUrl, localPath); return { success: true }; } catch (error) { + console.error("Error in git:clone:", error); return { success: false, error: (error as Error).message }; } }, diff --git a/src/renderer/main.tsx b/src/renderer/main.tsx index b15cbca7..1a5629c4 100644 --- a/src/renderer/main.tsx +++ b/src/renderer/main.tsx @@ -9,6 +9,19 @@ import { PerfLogger } from "./utils/perfLogger"; PerfLogger.mark("main.tsx execution started"); +// Global error handlers for renderer process +window.addEventListener('error', (event) => { + console.error('Global error caught:', event.error); + // Prevent the error from crashing the renderer + event.preventDefault(); +}); + +window.addEventListener('unhandledrejection', (event) => { + console.error('Unhandled promise rejection:', event.reason); + // Prevent the error from crashing the renderer + event.preventDefault(); +}); + const beforeQueryClient = performance.now(); const queryClient = new QueryClient({ defaultOptions: { diff --git a/src/renderer/services/github.ts b/src/renderer/services/github.ts index 0ff11f13..d3de9802 100644 --- a/src/renderer/services/github.ts +++ b/src/renderer/services/github.ts @@ -222,9 +222,14 @@ export class GitHubAPI { repo: string, state: "open" | "closed" | "all" = "open", ): Promise { - // Use lightweight GraphQL query for better performance - // Only fetch essential fields, not nested reviews/comments - return this.getPullRequestsGraphQLLight(owner, repo, state); + try { + // Use lightweight GraphQL query for better performance + // Only fetch essential fields, not nested reviews/comments + return await this.getPullRequestsGraphQLLight(owner, repo, state); + } catch (error) { + console.error(`Error fetching pull requests for ${owner}/${repo}:`, error); + throw error; + } } // Lightweight GraphQL query - only essential fields for list view