← Back to PRs

#14443: fix(telegram): skip General topic thread ID for all chat types (#14383)

by lailoo open 2026-02-12 04:31 View on GitHub →
channel: telegram size: XS
## Summary Fixes #14383 ## Problem When a Telegram Premium user enables Topics in a private bot chat, incoming messages include `message_thread_id: 1`. OpenClaw stores this thread context with `scope: "dm"`. On proactive sends (cron announcements, etc.), it passes `message_thread_id: 1` back to the Telegram API, which rejects it with: ``` GrammyError: Call to 'sendMessage' failed! (400: Bad Request: message thread not found) ``` ### Root Cause `buildTelegramThreadParams` in `src/telegram/bot/helpers.ts` only skipped thread ID 1 (General topic) when `scope === "forum"`: ```typescript if (normalized === TELEGRAM_GENERAL_TOPIC_ID && thread.scope === "forum") { return undefined; } ``` Private chat topics (Bot API 9.3+, Dec 2025) use `scope: "dm"`, so thread ID 1 was not skipped for DM chats. ## Fix Remove the `&& thread.scope === "forum"` condition so thread ID 1 is skipped for **all** chat types. Telegram rejects `message_thread_id=1` regardless of whether the chat is a forum supergroup or a private chat with Topics enabled. **Before:** ```typescript if (normalized === TELEGRAM_GENERAL_TOPIC_ID && thread.scope === "forum") { ``` **After:** ```typescript if (normalized === TELEGRAM_GENERAL_TOPIC_ID) { ``` ## Effect on User Experience **Before fix:** Proactive sends (cron jobs, announcements) to Telegram Premium users with Topics enabled in private bot chats fail with `400: Bad Request: message thread not found`. **After fix:** Proactive sends succeed by omitting `message_thread_id` when the thread ID is 1 (General topic), matching the behavior already in place for forum supergroups. ## Testing - ✅ 39 tests pass (`pnpm vitest run src/telegram/bot/helpers.test.ts src/telegram/bot/delivery.test.ts src/telegram/draft-stream.test.ts`) - ✅ Lint passes (`pnpm oxlint` on changed files) - Updated 3 test files to match new behavior - Added regression tests for non-General DM thread IDs (id=42, id=77) to ensure they still pass through <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adjusts Telegram thread parameter construction so that `message_thread_id=1` (the “General” topic) is omitted for *all* chat types, not just forum supergroups. This addresses a failure mode where private bot chats with Topics enabled (Premium) include `message_thread_id: 1` on inbound messages, and OpenClaw would echo that back on proactive sends, causing Telegram to reject the request. Tests were updated/added across delivery and draft stream paths to assert that DM threads with id=1 now omit `message_thread_id`, while non-General DM thread IDs still pass through. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - Change is narrowly scoped to `buildTelegramThreadParams` behavior for `message_thread_id=1`, and corresponding tests were updated/added to lock in the new behavior across delivery and draft-stream code paths. No other thread-handling helpers were modified. - No files require special attention <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs