thedotmack/claude-mem · warning
Failed to send Telegram notification
Error message
Failed to send Telegram notification
What it means
TelegramNotifier posts one message per matching observation via postOne (Telegram Bot API sendMessage). This warning fires when an individual send fails — network error, 400 for malformed text or a bad chat id, 401 for an invalid bot token, 403 when the bot was never started in the chat, or 429 rate limiting — and the loop continues with remaining observations. One failure never aborts the batch.
Source
Thrown at src/services/integrations/TelegramNotifier.ts:101
return;
}
const { observations, observationIds, project, memorySessionId } = input;
for (let i = 0; i < observations.length; i++) {
const obs = observations[i];
const matchesType = triggerTypes.includes(obs.type);
const matchesConcept = obs.concepts.some(c => triggerConcepts.includes(c));
if (!matchesType && !matchesConcept) {
continue;
}
const observationId = observationIds[i];
try {
const text = formatMessage(obs, project, memorySessionId, observationId);
await postOne(botToken, chatId, text);
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
logger.warn('TELEGRAM', 'Failed to send Telegram notification', {
observationId,
project,
memorySessionId,
type: obs.type,
}, err);
}
}
}
View on GitHub (pinned to e2d1df569a)
Solutions
- Read the logged error: 401 → fix the bot token; 400/403 → verify chatId and that the bot was started in that chat; 429 → reduce notification frequency.
- Truncate or split message text to stay under Telegram's 4096-character limit.
- Verify credentials directly: curl 'https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<ID>&text=ping'.
- Allow egress to api.telegram.org if a firewall or proxy is blocking it.
Example fix
// before: long observations exceed Telegram's 4096-char limit await postOne(botToken, chatId, text); // after: clamp the payload before sending await postOne(botToken, chatId, text.slice(0, 4096));
Defensive patterns
Strategy: retry
Validate before calling
// verify credentials once before enabling Telegram notifications
const res = await fetch(`https://api.telegram.org/bot${botToken}/getMe`);
if (!res.ok) throw new Error(`invalid bot token (HTTP ${res.status})`);
// then confirm the chat accepts the bot
const send = await fetch(`https://api.telegram.org/bot${botToken}/sendMessage?chat_id=${chatId}&text=ping`); Try / catch
for (const obs of matching) {
try {
await postOne(botToken, chatId, clampMessage(formatMessage(obs)));
} catch (e) {
if ((e as Error).message.includes('429')) {
await sleep(retryAfterMs(e) ?? 1000); // honor retry_after, then retry once
await postOne(botToken, chatId, clampMessage(formatMessage(obs)));
}
// other errors: log and continue — never abort the batch
}
} Prevention
- Call getMe at startup to fail fast on bad tokens.
- Clamp message bodies to 4096 characters before sending.
- Honor retry_after on 429 responses and space out bursts of notifications.
- Ensure the user pressed Start in the chat before relying on it.
When it happens
Trigger: await postOne(botToken, chatId, text) throws: invalid or revoked bot token, wrong chatId, message text exceeding Telegram's 4096-character limit, 429 rate limiting during bursts of observations, or no network egress to api.telegram.org.
Common situations: Revoked bot token; user never pressed Start in the chat (403 chat not found); corporate firewall blocking Telegram; a long observation blowing the length limit; bursts of observations tripping rate limits.
Related errors
- Failed to locate codex via where; falling back to codex.cmd
- Failed to disable Codex transcript AGENTS.md context
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/5b8d35397a95cffd.
Report an issue: GitHub.