Skip to content

Bug: Persian taker message not delivered due to Telegram MarkdownV2 parse error — proposed fallback fix #882

Open

Description

@mgatmiri

Summary

When a user with language set to Persian (fa) takes an order, the bot sometimes does not send the taker message. Root cause: the Persian translation for the key you_took_someone_order can contain characters that break Telegram's MarkdownV2 parsing, causing bot.telegram.sendMessage(...) to throw and the message not to reach the taker.

Reproduction

  1. Set a Telegram user language to Persian (fa) in the bot.
  2. Publish an order (sell/buy) and have another user take it.
  3. Observe that the taker (buyer/seller) does not receive the "you took order" message and logs show a MarkdownV2 parse-related error.

Proposed fix

Wrap the sendMessage call in beginTakeSellMessage with a try/catch that:

  • first attempts to send with parse_mode: 'MarkdownV2' (preserve intended formatting for safe locales),
  • on failure retries once without parse_mode as a safe fallback.

Minimal patch (applies to bot/messages.ts, function beginTakeSellMessage):

const message = ctx.i18n.t('you_took_someone_order', { expirationTime });
try {
await bot.telegram.sendMessage(buyer.tg_id, message, { parse_mode: 'MarkdownV2' });
} catch (err) {
logger.error('Failed to send MarkdownV2 message, retrying without parse_mode', err);
try { await bot.telegram.sendMessage(buyer.tg_id, message); } catch (err2) { logger.error('Retry without parse_mode also failed', err2); }
}

Why this is safe

  • Keeps MarkdownV2 for locales/translations that are already Markdown-safe.
  • Ensures users still receive the message when translations contain unescaped characters.
  • Minimal and local change; no behaviour change for other flows.

Files changed (local patch created)

  • bot/messages.ts (beginTakeSellMessage) — patch saved locally as:
    C:\Users\gatmiri.majid.copilot\session-state\22f19408-ad09-4767-974a8a675dc4a3a9\files\0001-Fix-fallback-for-MarkdownV2-send-in-beginTakeSellMes.patch

Testing

  • Run the bot (npm run dev or npm start). Set a user language to fa and take an order. Taker should receive the message.
  • If errors still occur, inspect logs for Telegram parse errors and escape MarkdownV2 special chars in locales/fa.yaml (key: you_took_someone_order).

Next steps

  • Apply the change and merge into main/release branch.
  • Optional: sanitize/escape MarkdownV2 in locales/fa.yaml to keep full MarkdownV2 formatting.

If useful, I can open a PR directly if given push rights; otherwise please apply the patch above or run the included patch with git am.

Activity

  1. Matobi98 commented on Aug 1, 2026

    @Matobi98
    Collaborator

    Hi @mgatmiri,

    I tried to replicate this issue with the taker in Farsi and the maker in another language, then the maker in Farsi and the taker in another language, and finally both in Farsi. I couldn't reproduce the problem on current main (HEAD), so I dug a bit deeper.

    You mentioned the taker message is "sometimes" not sent, which makes me suspect this isn't actually related to MarkdownV2 escaping — the string you_took_someone_order in locales/fa.yaml is already properly escaped since #872, and I confirmed via logging that the message is built correctly and delivered successfully in every scenario I tried.

    My biggest suspicion is that the real cause lies elsewhere: in beginTakeSellMessage (bot/messages.ts), the sendMessage call to notify the taker is wrapped in a try/catch that only calls logger.error(error) on failure, with no retry and no alert to anyone. So if the send fails for any reason — Telegram flood control (429), a transient network error, or anything else that throws inside that block — the order still gets saved as taken in the DB, but the taker never receives the message and nobody is notified that it failed.

    Could it be that this issue isn't actually caused by the MarkdownV2 problem, but by this other failure mode instead? If you have logs or a screenshot from when you saw the error, that would help a lot narrowing it down.

    Anyway, happy to help dig into this further if anything else comes up!

  2. mgatmiri commented on Aug 5, 2026

    @mgatmiri
    Author

    Thank u fot looking into the issue. Honestly i'm a non-techy user just trying to report ehat my selliw persian users have been experiencing fir the couple months ago. Here's one example:
    image
    Here, the taker took the above sell order a couple of times while lang was set to farsi, and the bot doesn't respond, then sends a message that says "no invoice was sent ..."
    Then, when lang is set to eng by the taker, problem is solved.

    Screenshot messages Date: 5 Aug 2026 - 14:55 (UTC+3:30)

  3. ToRyVand commented on Aug 10, 2026

    @ToRyVand
    Contributor

    I'd like to take this one. I traced it on current main: beginTakeSellMessage already wraps its sends in a try/catch, but the catch only logs — so when the MarkdownV2 send of you_took_someone_order throws, the taker message is silently lost, exactly as described.

    This complements the merged #872 (which escaped reserved chars in the Farsi locale) rather than replacing it: escaping is fragile (any new unescaped char reintroduces the bug), whereas the proposed retry-without-parse_mode fallback guarantees the taker still receives the message even if a translation slips through. Same resilience principle I'm applying in #595 (a send failure to one party shouldn't drop the message).

    I'll wrap just the you_took_someone_order send with the MarkdownV2→plain fallback and add a regression test. Could you assign it to me?

  4. grunch commented on Aug 10, 2026

    @grunch
    Member

    @ToRyVand go ahead 👍🏽

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions