Fix #4501: Handle unhandled promise rejections in Telegram polling
- Add global unhandled rejection handler in gateway startup - Properly await runner.stop() in Telegram monitor to prevent unhandled rejections - Ensure runner cleanup in finally block to prevent lingering promises - Log rejections instead of crashing the gateway Fixes issue where Telegram Bot API network failures during idle polling would cause unhandled promise rejections and crash the gateway process. The fix adds defensive error handling at both the gateway level (global handler) and the Telegram provider level (proper promise cleanup).
This commit is contained in:
parent
7150268f84
commit
0639c7bf1f
@ -148,6 +148,19 @@ export async function startGatewayServer(
|
||||
port = 18789,
|
||||
opts: GatewayServerOptions = {},
|
||||
): Promise<GatewayServer> {
|
||||
// Install global unhandled rejection handler to prevent gateway crashes
|
||||
// from background promises (e.g., Telegram polling, network operations)
|
||||
const handleUnhandledRejection = (reason: unknown, promise: Promise<unknown>) => {
|
||||
const formatted = reason instanceof Error ? reason.message : String(reason);
|
||||
log.error(`unhandled promise rejection: ${formatted}`);
|
||||
// Log additional details for debugging
|
||||
if (reason instanceof Error && reason.stack) {
|
||||
log.debug(`rejection stack: ${reason.stack}`);
|
||||
}
|
||||
// Don't crash the gateway - log and continue
|
||||
};
|
||||
process.on("unhandledRejection", handleUnhandledRejection);
|
||||
|
||||
// Ensure all default port derivations (browser/canvas) see the actual runtime port.
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(port);
|
||||
logAcceptedEnvOption({
|
||||
@ -572,6 +585,9 @@ export async function startGatewayServer(
|
||||
|
||||
return {
|
||||
close: async (opts) => {
|
||||
// Remove unhandled rejection handler on shutdown
|
||||
process.off("unhandledRejection", handleUnhandledRejection);
|
||||
|
||||
if (diagnosticsEnabled) {
|
||||
stopDiagnosticHeartbeat();
|
||||
}
|
||||
|
||||
@ -161,7 +161,12 @@ export async function monitorTelegramProvider(opts: MonitorTelegramOpts = {}) {
|
||||
const runner = run(bot, createTelegramRunnerOptions(cfg));
|
||||
const stopOnAbort = () => {
|
||||
if (opts.abortSignal?.aborted) {
|
||||
void runner.stop();
|
||||
// Properly await runner.stop() to prevent unhandled rejections
|
||||
runner.stop().catch((err) => {
|
||||
(opts.runtime?.error ?? console.error)(
|
||||
`telegram: runner stop failed: ${formatErrorMessage(err)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
opts.abortSignal?.addEventListener("abort", stopOnAbort, { once: true });
|
||||
@ -194,6 +199,13 @@ export async function monitorTelegramProvider(opts: MonitorTelegramOpts = {}) {
|
||||
}
|
||||
} finally {
|
||||
opts.abortSignal?.removeEventListener("abort", stopOnAbort);
|
||||
// Ensure runner is stopped to prevent lingering promises
|
||||
try {
|
||||
await runner.stop();
|
||||
} catch (stopErr) {
|
||||
// Suppress errors from runner.stop() in finally block
|
||||
// (already logged by stopOnAbort if abort-triggered)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user