fix(discord): prevent uncaught gateway errors from crashing the process

Move cleanup() after disconnect() in waitForDiscordGatewayStop so the
error listener is still active during disconnect. Add a safety error
listener in the lifecycle finally block to suppress late errors emitted
by Carbon during teardown.

Fixes the "Max reconnect attempts (0) reached after code 1006" uncaught
exception that kills the entire gateway process when a Discord WebSocket
drops and reconnection fails.
This commit is contained in:
sfwn
2026-03-25 10:51:28 +08:00
committed by Peter Steinberger
parent 247f82119c
commit 731016472c
2 changed files with 11 additions and 2 deletions

View File

@@ -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);
}
};

View File

@@ -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();