From 8b4be2fdd4f92c981ea8bead8aef860502786ba3 Mon Sep 17 00:00:00 2001 From: sheyanmin Date: Wed, 17 Jun 2026 16:10:13 +0800 Subject: [PATCH] fix: recover channel after stop timeout in health monitor When a channel stop times out (e.g. during a Telegram API outage), the channel enters recoveryStopTimedOut state. The health monitor's subsequent start call would set restartPending and return without actually starting the channel. If the stuck stop never completes, the channel stays in limbo forever with the health monitor retrying every cycle but never recovering. Fix: when the health monitor retries recovery (recoveryStartRequested already set), clean up the stuck task state and allow the channel to start normally. Closes #94008 --- src/gateway/server-channels.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/gateway/server-channels.ts b/src/gateway/server-channels.ts index a5ced7149ed2..7ddcc98b7590 100644 --- a/src/gateway/server-channels.ts +++ b/src/gateway/server-channels.ts @@ -456,8 +456,25 @@ export function createChannelManager(opts: ChannelManagerOptions): ChannelManage if (manuallyStopped.has(rKey)) { return; } - recoveryStartRequested.add(rKey); - setRuntime(channelId, id, { accountId: id, restartPending: true }); + // When a previous stop timed out and the health monitor is + // requesting recovery again, clean up the stuck task so the + // channel can actually restart instead of staying in limbo. + if (recoveryStartRequested.has(rKey)) { + recoveryStopTimedOut.delete(rKey); + recoveryStartRequested.delete(rKey); + restartAttempts.delete(rKey); + store.aborts.delete(id); + store.tasks.delete(id); + setRuntime(channelId, id, { + accountId: id, + restartPending: false, + reconnectAttempts: 0, + }); + } else { + recoveryStartRequested.add(rKey); + setRuntime(channelId, id, { accountId: id, restartPending: true }); + return; + } } return; }