thedotmack/claude-mem · error

Telegram API responded

Error message

Telegram API responded ${status} ${statusText}

What it means

postTelegramMessage sends a message to the Telegram Bot API and throws when the HTTP response is not ok (!response.ok), embedding the HTTP status code and status text. This surfaces API-level failures such as bad tokens, malformed payloads, or rate limiting.

Solutions

  1. Read the status: 401 means fix TELEGRAM_BOT_TOKEN; 400 usually means unescaped MarkdownV2 characters — escape _*[]()~`>#+-=|{}.!
  2. For 403/400 chat errors, ensure the user has started a chat with the bot and the chat_id is correct.
  3. For 429, implement backoff honoring response 'retry_after' (see Telegram error parameters) and reduce send frequency.
  4. Temporarily remove parse_mode: 'MarkdownV2' to check whether the formatting is the cause.

Example fix

// before
const res = await fetch(url, { method: 'POST', body: JSON.stringify({ text: raw, parse_mode: 'MarkdownV2' }) });
// after
const res = await fetch(url, { method: 'POST', body: JSON.stringify({ text: escapeMarkdownV2(raw), parse_mode: 'MarkdownV2' }) });
if (!res.ok) console.error('Telegram error', res.status, await res.text());
Defensive patterns

Strategy: retry

Validate before calling

if (!botToken || !/^\d+:[\w-]{30,}$/.test(botToken)) throw new Error('invalid bot token');
if (!chatId) throw new Error('chatId required');

Try / catch

try {
  await postTelegramMessage(text);
} catch (err) {
  const m = /responded (\d+)/.exec(String(err));
  const status = m ? Number(m[1]) : 0;
  if (status === 429) await sleep(backoff); // retry
  else if (status === 400) logger.warn('MarkdownV2 parse error — escape special chars');
  else logger.error('Telegram send failed', { status }, err);
}

Prevention

When it happens

Trigger: Called by notifyTelegram or deliverSessionWrapup while the Telegram API returns 400 (bad chat_id / MarkdownV2 parse error), 401 (invalid bot token), 403 (bot blocked), 404 (wrong method), or 429 (rate limit).

Common situations: Expired or revoked bot token; chat_id never started the bot; MarkdownV2 message text contains unescaped special characters causing a 400; sending too many messages and hitting 429.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/c7d9e122c2df4956. Report an issue: GitHub.

Appendix: source

Thrown at src/services/integrations/telegram-transport.ts:26

  botToken: string,
  chatId: string,
  text: string,
  fetchImpl: typeof fetch = globalThis.fetch,
): Promise<void> {
  const url = `https://api.telegram.org/bot${botToken}/sendMessage`;
  const response = await fetchImpl(url, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({
      chat_id: chatId,
      text,
      parse_mode: 'MarkdownV2',
    }),
  });
  if (!response.ok) {
    const status = response.status;
    const statusText = response.statusText;
    throw new Error(`Telegram API responded ${status} ${statusText}`);
  }
}

View on GitHub (pinned to d8bc9755e7)