From c6b4de520af848bdfa577146aa8e2e001c87911d Mon Sep 17 00:00:00 2001 From: mac mimi Date: Mon, 2 Feb 2026 22:21:44 +0100 Subject: [PATCH] fix(telegram): recover from grammY "timed out" long-poll errors (#7239) grammY getUpdates returns "Request to getUpdates timed out after 500 seconds" but RECOVERABLE_MESSAGE_SNIPPETS only had "timeout". Since "timed out".includes("timeout") === false, the error was not classified as recoverable, causing the polling loop to exit permanently. Add "timed out" to RECOVERABLE_MESSAGE_SNIPPETS so the polling loop retries instead of dying silently. Fixes #7239 Fixes #7255 --- src/telegram/network-errors.test.ts | 5 +++++ src/telegram/network-errors.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/src/telegram/network-errors.test.ts b/src/telegram/network-errors.test.ts index bb4b0ef1b..c435320bd 100644 --- a/src/telegram/network-errors.test.ts +++ b/src/telegram/network-errors.test.ts @@ -40,6 +40,11 @@ describe("isRecoverableTelegramNetworkError", () => { expect(isRecoverableTelegramNetworkError(new Error("invalid token"))).toBe(false); }); + it("detects grammY 'timed out' long-poll errors (#7239)", () => { + const err = new Error("Request to 'getUpdates' timed out after 500 seconds"); + expect(isRecoverableTelegramNetworkError(err)).toBe(true); + }); + // Grammy HttpError tests (issue #3815) // Grammy wraps fetch errors in .error property, not .cause describe("Grammy HttpError", () => { diff --git a/src/telegram/network-errors.ts b/src/telegram/network-errors.ts index 392df9781..75c22ea7f 100644 --- a/src/telegram/network-errors.ts +++ b/src/telegram/network-errors.ts @@ -37,6 +37,7 @@ const RECOVERABLE_MESSAGE_SNIPPETS = [ "socket hang up", "getaddrinfo", "timeout", // catch timeout messages not covered by error codes/names + "timed out", // grammY getUpdates returns "timed out after X seconds" (not matched by "timeout") ]; function normalizeCode(code?: string): string {