Skip to content

fix(telegram): preserve reply text in threaded mode dispatch#17769

Closed
Glucksberg wants to merge 1 commit intoopenclaw:mainfrom
Glucksberg:fix/7186-telegram
Closed

fix(telegram): preserve reply text in threaded mode dispatch#17769
Glucksberg wants to merge 1 commit intoopenclaw:mainfrom
Glucksberg:fix/7186-telegram

Conversation

@Glucksberg
Copy link
Contributor

@Glucksberg Glucksberg commented Feb 16, 2026

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 Summary

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.

Confidence Score: 5/5

  • 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.

Last reviewed commit: 34548ee

@steipete
Copy link
Contributor

Closing as AI-assisted stale-fix triage.

Linked issue #7186 ("Telegram threaded replies fail with empty message text") is currently CLOSED and was closed on 2026-02-24T04:28:56Z with state reason NOT_PLANNED.
Given that issue state, this fix PR is no longer needed in the active queue and is being closed as stale.

If the underlying bug is still reproducible on current main, please reopen this PR (or open a new focused fix PR) and reference both #7186 and #17769 for fast re-triage.

@steipete
Copy link
Contributor

Closed after AI-assisted stale-fix triage (closed issue duplicate/stale fix).

@steipete steipete closed this Feb 24, 2026
@Glucksberg
Copy link
Contributor Author

Follow-up: this bug now has two active implementation paths:

#25096 was opened as a narrow/small-diff alternative for faster merge if maintainers prefer minimal scope.

Once one path is chosen for merge, the other can be closed by either me or the maintainer to keep queue hygiene clean.

Fresh repro evidence is documented in #25091.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Telegram threaded replies fail with empty message text

2 participants