fix(gateway/telegram): fallback to plain text on Markdown parse failure#946
Open
chaodu-agent wants to merge 4 commits into
Open
fix(gateway/telegram): fallback to plain text on Markdown parse failure#946chaodu-agent wants to merge 4 commits into
chaodu-agent wants to merge 4 commits into
Conversation
Closes #871. When Telegram rejects a message due to Markdown parse errors (unescaped special characters in URLs, Chinese text, code), the adapter now detects the API-level failure (ok: false) and retries without parse_mode. Previously, `let _ =` discarded the response entirely, causing messages to silently disappear while the bot still showed success reactions.
added 2 commits
May 28, 2026 11:15
Address review findings: - F1: Only retry as plain text when description contains 'parse' or 'entities'. Other errors (429 rate limit, 403 forbidden) are logged but not retried to avoid wasting API calls. - F2: Plain text fallback now checks response and logs error if it also fails, improving observability.
Address 普渡法師 review: - F2: Replace fragile desc.contains() string matching with error_code == 400 check. Telegram 400 = Bad Request (parse errors); 429/403/etc are not retried. - F3: Handle JSON decode failure explicitly with warn log instead of unwrap_or_default() which could silently trigger false retries. - F1 (MarkdownV2): Intentionally deferred — switching parse_mode is a behavior change beyond this bug fix scope. MarkdownV2 requires more escaping and would cause more failures without a full escape pipeline. - F4 (tests): No test framework exists for gateway telegram adapter. Tracked as follow-up.
Contributor
OpenAB PR ScreeningThis is auto-generated by the OpenAB project-screening flow for context collection and reviewer handoff.
Screening reportblocked at the write step. i verified with `gh` that:
then the command sandbox started failing even for so i could not post the GitHub comment or move the project item. i’m not going to pretend that happened. screening report prepared: <!-- openab-project-screening -->
## Intent
Fix Telegram message delivery failures where Telegram accepts the HTTP request but rejects Markdown entity parsing at the API layer. The operator-visible symptom is misleading success handling: users can see a success reaction while the actual Telegram reply is silently dropped.
## Feat
Fix work. The Telegram gateway adapter now attempts `sendMessage` with Markdown first, inspects the Telegram API response, and retries as plain text without `parse_mode` when Telegram returns an API-level failure such as `can't parse entities`.
## Who It Serves
Telegram users and gateway runtime operators. Users get the message instead of a false-success drop; operators get warning logs instead of a swallowed API response.
## Rewritten Prompt
Update `gateway/src/adapters/telegram.rs` so outbound Telegram text messages are not silently lost when Markdown parsing fails. Send with the existing Markdown behavior first, parse the Telegram API response body, and if the response reports `ok: false`, log the failure and retry the same message as plain text without `parse_mode`. Preserve existing network-error handling, avoid retry loops, and add or keep focused validation around the response parsing path where practical.
## Merge Pitch
This should move forward because it addresses a real delivery correctness bug with a narrow one-file change. The risk profile is low: the fallback only triggers after Telegram rejects the formatted send, and the second attempt trades formatting for delivery. The main reviewer concern is likely whether all `ok: false` responses should fall back to plain text or whether retry should be limited to parse/entity errors to avoid masking unrelated Telegram API failures.
## Best-Practice Comparison
OpenClaw's durable delivery model would treat this as an explicit delivery failure with retry/backoff and run logs; this PR is a smaller adapter-local version of that idea, improving response inspection and retry behavior without adding job persistence. Hermes Agent's scheduling and persisted prompt model does not directly apply because this is synchronous outbound message delivery, not scheduled execution. The relevant overlap is explicit failure handling: do not discard API responses when they determine user-visible delivery.
## Implementation Options
Conservative: accept this PR's adapter-local fallback as-is, with reviewer attention on response parsing and warning quality. This is fastest and fixes the user-visible drop.
Balanced: restrict fallback to Telegram parse/entity failures, log non-parse `ok: false` responses as hard send failures, and add a focused unit test or helper-level test for Markdown failure response handling. This keeps delivery resilient without hiding unrelated API errors.
Ambitious: introduce a small shared gateway send-result abstraction for outbound adapters, so API-level failures, retries, and delivery logs are represented consistently across Telegram and future adapters. This is more maintainable long term but larger than the immediate bug requires.
## Comparison Table
| Option | Speed | Complexity | Reliability | Maintainability | User Impact | Fit for OpenAB now |
|---|---:|---:|---:|---:|---:|---|
| Conservative | High | Low | Medium | Medium | High | Good for quick unblock |
| Balanced | Medium | Low-Medium | High | High | High | Best fit |
| Ambitious | Low | High | High | High | High | Better as follow-up |
## Recommendation
Proceed with the balanced path if review can request a small refinement: fallback only for Telegram Markdown/entity parse failures and keep other `ok: false` responses visible as send failures. If the current implementation already cleanly exposes the failed response and avoids loops, this is suitable for Masami or Pahud follow-up review as a narrow correctness fix. Broader delivery persistence and adapter-wide retry semantics should be split out.
Agent-ran OpenAB PR screening. Feedback welcome; react thumbs-up if useful. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #871.
When Telegram rejects a message due to Markdown parse errors (unescaped special characters in URLs, Chinese text, code snippets), the adapter now detects the API-level failure (
ok: false) and retries withoutparse_mode.Problem
Two issues:
let _ =discarded the HTTP response — Telegram API errors (ok: false) were never checkedparse_mode: "Markdown"is strict — unescaped_,*,[,], ``` cause rejectionFix
Try with Markdown first. If Telegram returns
ok: false, log a warning and retry as plain text (noparse_mode). Network errors are still logged without retry.Changes
gateway/src/adapters/telegram.rsValidation
cargo check— no C linker in agent environment; CI will verifyDiscord Discussion URL: https://discord.com/channels/1491295327620169908/1504195583676780605