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
- Read the status: 401 means fix TELEGRAM_BOT_TOKEN; 400 usually means unescaped MarkdownV2 characters — escape _*[]()~`>#+-=|{}.!
- For 403/400 chat errors, ensure the user has started a chat with the bot and the chat_id is correct.
- For 429, implement backoff honoring response 'retry_after' (see Telegram error parameters) and reduce send frequency.
- 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
- Escape MarkdownV2 special characters in message text.
- Verify the bot token and that users started the bot chat.
- Rate-limit sends to avoid 429s.
- Log response bodies for diagnosis when possible.
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)