diff --git a/extensions/discord/src/monitor.gateway.ts b/extensions/discord/src/monitor.gateway.ts index d8e83a12a1e..8c89cf14567 100644 --- a/extensions/discord/src/monitor.gateway.ts +++ b/extensions/discord/src/monitor.gateway.ts @@ -33,10 +33,12 @@ export async function waitForDiscordGatewayStop( return; } settled = true; - cleanup(); try { gateway?.disconnect?.(); } finally { + // remove listeners after disconnect so late "error" events emitted + // during disconnect are still handled instead of becoming uncaught + cleanup(); resolve(); } }; @@ -45,10 +47,10 @@ export async function waitForDiscordGatewayStop( return; } settled = true; - cleanup(); try { gateway?.disconnect?.(); } finally { + cleanup(); reject(err); } }; diff --git a/extensions/discord/src/monitor/provider.lifecycle.ts b/extensions/discord/src/monitor/provider.lifecycle.ts index 884a0bded57..0ba9cd568e9 100644 --- a/extensions/discord/src/monitor/provider.lifecycle.ts +++ b/extensions/discord/src/monitor/provider.lifecycle.ts @@ -420,6 +420,13 @@ export async function runDiscordGatewayLifecycle(params: { } } finally { lifecycleStopping = true; + // attach a safety listener before releasing other listeners so that late + // "error" events emitted by Carbon during teardown do not become uncaught + // exceptions and crash the entire gateway process. + const suppressLateError = (err: unknown) => { + params.runtime.error?.(danger(`discord: suppressed late gateway error: ${String(err)}`)); + }; + gatewayEmitter?.on("error", suppressLateError); params.releaseEarlyGatewayErrorGuard?.(); unregisterGateway(params.accountId); stopGatewayLogging();