Skip to content

bug: Telegram sendMessage silently fails on Markdown parse errors #871

@chaodu-agent

Description

@chaodu-agent

Summary

The Telegram adapter silently drops messages when Telegram rejects the Markdown formatting. The bot shows reactions (thinking → done) but no text reply is delivered.

Root Cause

In gateway/src/adapters/telegram.rs (line ~335):

let _ = client
    .post(&url)
    .json(&serde_json::json!({
        "chat_id": reply.channel.id,
        "text": reply.content.text,
        "message_thread_id": reply.channel.thread_id,
        "parse_mode": "Markdown",
    }))
    .send()
    .await
    .map_err(|e| error!("telegram send error: {e}"));

Two issues:

  1. let _ = discards the response — Telegram API errors (HTTP 200 with "ok": false) are never checked. Only network-level errors are caught by map_err.

  2. "parse_mode": "Markdown" is strict — If the agent response contains unescaped _, *, [, ], ` (very common in Chinese text, URLs, or code), Telegram returns "Bad Request: can't parse entities" and the message is never delivered.

Reproduction

  1. Send an image to the bot via Telegram with a caption like "幫我找這條牛仔褲的連結"
  2. Agent responds with text containing URLs and markdown-like characters
  3. Bot shows reactions (✅) but no text message appears in chat

Suggested Fix

Fallback pattern — try with Markdown, retry as plain text on failure:

let resp = client.post(&url)
    .json(&serde_json::json!({
        "chat_id": reply.channel.id,
        "text": &reply.content.text,
        "message_thread_id": reply.channel.thread_id,
        "parse_mode": "Markdown",
    }))
    .send().await;

match resp {
    Ok(r) => {
        let body: serde_json::Value = r.json().await.unwrap_or_default();
        if body["ok"].as_bool() != Some(true) {
            warn!("Markdown send failed: {}, retrying as plain text", body["description"]);
            let _ = client.post(&url)
                .json(&serde_json::json!({
                    "chat_id": reply.channel.id,
                    "text": &reply.content.text,
                    "message_thread_id": reply.channel.thread_id,
                }))
                .send().await;
        }
    }
    Err(e) => error!("telegram send error: {e}"),
}

Impact

Any agent response with special characters silently disappears. User sees reactions but no reply — appears broken.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingp1High — address this sprinttelegram

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions