{"record":{"id":"c7d9e122c2df4956","repo":"thedotmack/claude-mem","slug":"telegram-api-responded-status-statustext","errorCode":null,"errorMessage":"Telegram API responded ${status} ${statusText}","messagePattern":"Telegram API responded (.+?) (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/integrations/telegram-transport.ts","lineNumber":26,"sourceCode":"  botToken: string,\n  chatId: string,\n  text: string,\n  fetchImpl: typeof fetch = globalThis.fetch,\n): Promise<void> {\n  const url = `https://api.telegram.org/bot${botToken}/sendMessage`;\n  const response = await fetchImpl(url, {\n    method: 'POST',\n    headers: { 'content-type': 'application/json' },\n    body: JSON.stringify({\n      chat_id: chatId,\n      text,\n      parse_mode: 'MarkdownV2',\n    }),\n  });\n  if (!response.ok) {\n    const status = response.status;\n    const statusText = response.statusText;\n    throw new Error(`Telegram API responded ${status} ${statusText}`);\n  }\n}\n","sourceCodeStart":8,"sourceCodeEnd":29,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/integrations/telegram-transport.ts#L8-L29","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nconst res = await fetch(url, { method: 'POST', body: JSON.stringify({ text: raw, parse_mode: 'MarkdownV2' }) });\n// after\nconst res = await fetch(url, { method: 'POST', body: JSON.stringify({ text: escapeMarkdownV2(raw), parse_mode: 'MarkdownV2' }) });\nif (!res.ok) console.error('Telegram error', res.status, await res.text());","handlingStrategy":"retry","validationCode":"if (!botToken || !/^\\d+:[\\w-]{30,}$/.test(botToken)) throw new Error('invalid bot token');\nif (!chatId) throw new Error('chatId required');","typeGuard":null,"tryCatchPattern":"try {\n  await postTelegramMessage(text);\n} catch (err) {\n  const m = /responded (\\d+)/.exec(String(err));\n  const status = m ? Number(m[1]) : 0;\n  if (status === 429) await sleep(backoff); // retry\n  else if (status === 400) logger.warn('MarkdownV2 parse error — escape special chars');\n  else logger.error('Telegram send failed', { status }, err);\n}","preventionTips":["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."],"tags":["network","http","telegram","api"],"backgroundTag":"http-error-response","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}