← Back to PRs

#21898: fix(telegram): auto-detect captionable messages for editMessageCaption

by ptrkstr open 2026-02-20 14:08 View on GitHub →
channel: telegram size: M
## Summary - **Problem:** When editing a Telegram message containing media (photo, video, audio, document, animation), OpenClaw calls `api.editMessageText()` — Telegram rejects this with `400: there is no text in the message to edit` - **Why it matters:** Any `message(action=edit)` call on a captionable message silently fails with a 400 error, leaving the UI in an inconsistent state - **What changed:** `editMessageTelegram` in `send.ts` now auto-detects captionable messages by catching the specific 400 and retrying with `editMessageCaption`; buttons-only updates use `editMessageReplyMarkup` directly - **What did NOT change:** The generic `message` tool interface is unchanged — no new parameters, no Telegram-specific details exposed to callers; all other channel adapters untouched ## Change Type - [x] Bug fix ## Scope - [x] Integrations ## Linked Issue/PR - Closes # - Related # ## User-visible / Behavior Changes `message(action=edit)` on messages containing photo, video, audio, document, or animation now succeeds instead of throwing a 400 error. No config or interface changes. ## Security Impact - New permissions/capabilities? `No` - Secrets/tokens handling changed? `No` - New/changed network calls? `Yes` - Command/tool execution surface changed? `No` - Data access scope changed? `No` - **Explanation:** Two new Telegram Bot API methods are now called (`editMessageCaption`, `editMessageReplyMarkup`). Both are standard endpoints scoped to the bot's existing token — no new capabilities or data access beyond what `editMessageText` already had. ## Repro + Verification ### Environment - OS: macOS Darwin 25.3.0 (arm64) - Runtime/container: Node.js v22.22.0 - Model/provider: anthropic/claude-sonnet-4-6 - Integration/channel: Telegram - Relevant config: Standard Telegram bot token ### Steps 1. Send a photo or video message via the `message` tool to a Telegram chat 2. Call `message(action=edit, messageId=..., message="updated caption")` on that message 3. Observe result ### Expected Caption updates successfully on the media message ### Actual (before fix) 400: Bad Request: there is no text in the message to edit ## Evidence - [x] Failing test/log before + passing after — 510/510 unit tests passing; 6 new tests added covering: - Auto-detect retry path (`editMessageText` → catch → `editMessageCaption`) - Buttons-only path (direct `editMessageReplyMarkup`) - Error propagation (non-matching errors still throw) - `MESSAGE_NOT_MODIFIED` swallowed as success on all paths ## Human Verification - **Verified scenarios:** All three code paths via unit tests; `MESSAGE_NOT_MODIFIED` handling; HTML parse mode fallback preserved on both text and caption paths - **Edge cases checked:** Non-matching 400 errors propagate normally; regex scoped tightly to the specific Telegram error string - **What I did not verify:** Live end-to-end manual test with a real Telegram bot (unit tests mock the API layer) ## Compatibility / Migration - Backward compatible? `Yes` - Config/env changes? `No` - Migration needed? `No` ## Failure Recovery - **How to disable/revert:** Revert `src/telegram/send.ts` to previous `editMessageTelegram` implementation - **Files/config to restore:** `src/telegram/send.ts` only - **Known bad symptoms:** Unexpected retry loops on 400 errors — check `NO_TEXT_IN_MESSAGE_RE` regex against actual Telegram error wording ## Risks and Mitigations - **Risk:** `NO_TEXT_IN_MESSAGE_RE` regex may not match if Telegram changes their error message wording - **Mitigation:** Failure mode is graceful — unmatched errors propagate as before (old behavior), no new failure modes introduced <!-- greptile_comment --> <h3>Greptile Summary</h3> Fixes message editing failures for Telegram media messages (photo, video, audio, document, animation) by auto-detecting captionable messages and retrying with the correct API method. **Key Changes:** - Added `NO_TEXT_IN_MESSAGE_RE` regex to detect Telegram's "no text in message" error - `editMessageTelegram` now catches the 400 error and retries with `editMessageCaption` for media messages - Added direct `editMessageReplyMarkup` path for buttons-only updates (works for both text and media) - Preserved HTML parse fallback behavior on both text and caption paths - All three code paths properly handle `MESSAGE_NOT_MODIFIED` as success **Test Coverage:** Six new tests cover all code paths: auto-detect retry, buttons-only, error propagation, and `MESSAGE_NOT_MODIFIED` handling. Implementation is backward compatible with no API surface changes. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk - The implementation follows a defensive error-handling pattern with graceful fallbacks. The regex is scoped tightly to the specific Telegram error message. Six comprehensive tests cover all code paths including edge cases (MESSAGE_NOT_MODIFIED handling, error propagation, buttons-only updates). The change is backward compatible with no API surface modifications and only affects the Telegram channel adapter. Failure mode is graceful—unmatched errors propagate as before. - No files require special attention <sub>Last reviewed commit: 2e0852c</sub> <!-- 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