#17769: fix(telegram): preserve reply text in threaded mode dispatch
channel: telegram
size: S
experienced-contributor
Cluster:
Telegram Message Handling Fixes
Fixes #7186
## Problem
In Telegram threaded mode, certain markdown-only inputs (e.g. `>`) render to empty HTML via `markdownToTelegramHtml()`. The empty string is then passed to `bot.api.sendMessage()`, which rejects it with a 400 error: *"message text is empty"*. The reply is silently lost.
## Fix
Instead of silently dropping messages when HTML is empty, this fix **falls back to sending the original plain text**:
- Extracts the fallback send logic into a reusable `sendPlainFallback()` helper (DRYs up the duplicated `sendMessage` call)
- When `markdownToTelegramHtml()` produces empty output, calls `sendPlainFallback()` instead of skipping
- Adds `EMPTY_TEXT_ERR_RE` to also catch edge cases where empty text slips past the static check at runtime
- If even the fallback text is empty, returns `undefined` gracefully
## Changes
- `src/telegram/bot/delivery.ts` — Refactored `sendTelegramText()` with early empty-HTML fallback, shared `sendPlainFallback()` helper, and `EMPTY_TEXT_ERR_RE` error catch
- `src/telegram/bot/delivery.test.ts` — Added test: "falls back to plain text when markdown renders to empty HTML in threaded mode"
## Tests
```
✓ falls back to plain text when markdown renders to empty HTML in threaded mode
```
All existing delivery tests pass.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a bug where Telegram threaded mode silently drops replies when markdown-only inputs (e.g., `>`) render to empty HTML via `markdownToTelegramHtml()`. The empty string caused Telegram's `sendMessage` API to reject with a 400 "message text is empty" error.
- **Early empty-HTML detection**: Adds a `!htmlText.trim()` check in `sendTelegramText()` to fall back to plain text before attempting the HTML send, avoiding the 400 error entirely.
- **DRY refactor**: Extracts the plain-text fallback logic into a shared `sendPlainFallback()` helper, eliminating the duplicated `sendMessage` call that existed in the parse-error catch block.
- **Runtime safety net**: Adds `EMPTY_TEXT_ERR_RE` to catch "message text is empty" errors at runtime in case the static check is bypassed.
- **Graceful empty handling**: When even the fallback text is empty, `sendPlainFallback()` returns `undefined` instead of throwing.
- Test added covering the specific scenario of `>` input in threaded (forum) mode.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it adds a defensive fallback path for an edge case without changing normal behavior.
- The changes are minimal and focused: an early guard for empty HTML output, a DRY refactor of existing fallback logic, and a runtime safety net regex. The normal (non-empty HTML) code path is unchanged. The added test covers the specific bug scenario. I traced through the full execution path for both the early-return and catch-block fallback and found no issues.
- No files require special attention.
<sub>Last reviewed commit: 34548ee</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#17629: fix(telegram): fall back to plain text when HTML formatter produces...
by Glucksberg · 2026-02-16
91.6%
#7218: fix(telegram): skip empty text messages in threaded mode
by ArsalanShakil · 2026-02-02
88.9%
#11340: Telegram: skip empty message text instead of throwing (#11238)
by lailoo · 2026-02-07
83.1%
#19213: Telegram: preserve DM topic thread in direct replies
by Kemalau · 2026-02-17
80.5%
#12936: fix(telegram): omit message_thread_id for private DM chats
by omair445 · 2026-02-09
79.8%
#4249: fix(telegram): properly nest link tags inside bold/italic formatting
by pradeeppeddineni · 2026-01-29
79.5%
#17953: fix(telegram): prevent silent message loss and duplicate messages i...
by zuyan9 · 2026-02-16
78.8%
#7261: fix(telegram): preserve DM topic thread id for outbound media
by ViffyGwaanl · 2026-02-02
78.6%
#19050: fix(telegram): skip message_thread_id for private chats to prevent ...
by Limitless2023 · 2026-02-17
78.3%
#17968: fix(telegram): restore DM topic thread ids with send-path fallback
by Leonccaa · 2026-02-16
77.9%