From 4b2592c27f9aa4dc98448630b16f61f2e5cf987e Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Thu, 2 Apr 2026 13:50:45 -0700 Subject: [PATCH] fix(rinbox): handle IMAP socket errors to prevent server crash-loop ImapFlow clients were created without .on('error') handlers. Socket timeouts emitted unhandled errors that crashed the entire process, taking down all 32 modules. Added error handlers to all 3 ImapFlow instantiation sites and a process-level uncaughtException/unhandledRejection safety net. Co-Authored-By: Claude Opus 4.6 --- modules/rinbox/mod.ts | 7 +++++++ server/index.ts | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/modules/rinbox/mod.ts b/modules/rinbox/mod.ts index 128a2d9..ebf8751 100644 --- a/modules/rinbox/mod.ts +++ b/modules/rinbox/mod.ts @@ -1112,6 +1112,7 @@ routes.post("/api/personal-inboxes", async (c) => { auth: { user: imap_user, pass: imap_pass }, logger: false, }); + client.on('error', () => {}); // swallow — validation only await client.connect(); await client.logout(); } catch (e: any) { @@ -1454,6 +1455,9 @@ async function syncMailbox(mailbox: SyncableMailbox) { tls: { rejectUnauthorized: IMAP_TLS_REJECT }, logger: false, }); + client.on('error', (err: Error) => { + console.error(`[Inbox] IMAP client error for ${mailbox.email}:`, err.message); + }); try { await client.connect(); @@ -1704,6 +1708,9 @@ async function syncAgentMailbox(creds: AgentImapCreds) { tls: { rejectUnauthorized: IMAP_TLS_REJECT }, logger: false, }); + client.on('error', (err: Error) => { + console.error(`[Inbox] Agent IMAP client error (${creds.email}):`, err.message); + }); try { await client.connect(); diff --git a/server/index.ts b/server/index.ts index d9eacfd..10e0b1c 100644 --- a/server/index.ts +++ b/server/index.ts @@ -103,6 +103,15 @@ import { SystemClock } from "./clock-service"; import type { ClockPayload } from "./clock-service"; import { miRoutes } from "./mi-routes"; +// ── Process-level error safety net (prevent crash on unhandled socket errors) ── +process.on('uncaughtException', (err) => { + console.error('[FATAL] Uncaught exception (swallowed):', err.message); + // Don't exit — keep the server running +}); +process.on('unhandledRejection', (reason) => { + console.error('[FATAL] Unhandled rejection (swallowed):', reason); +}); + // Register modules (order determines app-switcher menu position) registerModule(canvasModule); registerModule(pubsModule);