← Back to PRs

#11347: fix: scope Telegram update offset to bot token

by anooprdawar open 2026-02-07 18:28 View on GitHub →
channel: telegram stale
## Problem The update offset file (`~/.openclaw/telegram/update-offset-{account}.json`) was keyed only by account name, not by bot token. When a bot token changed (common during initial setup or debugging), the persisted `lastUpdateId` from the old token would silently reject **all** inbound messages from the new bot. `shouldSkipUpdate()` saw `updateId <= lastUpdateId` as always true because the old offset (e.g. 432M) was far ahead of the new bot's actual update IDs (e.g. 363M). ## Root Cause Discovered while debugging #11011. The offset file had no awareness of which bot it belonged to. Token changes left a stale, impossibly-high offset that caused every inbound message to be dedupe-skipped. ## Changes - **`update-offset-store.ts`**: Store `botId` (extracted from token) in the offset JSON. On read, validate `botId` matches the current token — discard offset if mismatched. - **`monitor.ts`**: Pass `botToken` through `readTelegramUpdateOffset` and `writeTelegramUpdateOffset` calls. - **Backward compatible**: Legacy files without `botId` field still work (no forced migration). - **Tests**: Added 5 new tests covering token change invalidation, backward compat, legacy file reads, and `extractBotIdFromToken`. ## Test Results ``` 48 test files | 405 tests — all passing ✅ ``` Fixes #11337 Related: #11011 <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR fixes a Telegram polling edge case where the persisted `lastUpdateId` offset was keyed only by account id. It now stores the bot’s numeric id (derived from the bot token) alongside the offset, and on read discards the stored offset if the current token belongs to a different bot. The monitor passes the token through to the offset store, and new tests cover token-change invalidation, backward-compat reads, legacy files, and bot-id extraction. <h3>Confidence Score: 4/5</h3> - Generally safe to merge once the token-parse mismatch case is addressed. - The change is localized and well-tested, but the current invalidation logic can still accept a stale offset when a `botToken` is provided but can’t be parsed into a bot id while the stored file has a `botId` (leading to the original skip-all-updates failure mode). - src/telegram/update-offset-store.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs