Telegram channel plugin: silent polling death on network drop
The Telegram channel plugin for Claude Code has a silent-death bug — grammY's bot.start() has no .catch() handler, so when the polling loop drops (network blip, API timeout), the process stays alive but stops receiving messages. No error, no reconnect, no log. Three-line fix: wrap in a retry with backoff.
Repro
- Start Claude with
--channels plugin:telegram@claude-plugins-official - Wait for a network interruption (or just enough time — long-polling connections drop)
- The bun process stays alive (visible in
ps) but has zero TCP connections (lsof -i -p <pid>returns nothing) - Bot stops receiving Telegram messages silently
Root cause
server.ts line 594:
void bot.start({
onStart: info => {
botUsername = info.username
process.stderr.write(`telegram channel: polling as @${info.username}\n`)
},
})
No .catch(), no bot.catch(). When the polling promise rejects, it's a fire-and-forget void — the error vanishes and polling stops permanently.
Fix
function startPolling() {
bot.start({
onStart: info => {
botUsername = info.username
process.stderr.write(`telegram channel: polling as @${info.username}\n`)
},
}).catch(err => {
process.stderr.write(`telegram channel: polling died — ${err?.message ?? err}\n`)
process.stderr.write(`telegram channel: restarting polling in 5s\n`)
setTimeout(startPolling, 5000)
})
}
bot.catch(err => {
process.stderr.write(`telegram channel: bot error — ${err?.message ?? err}\n`)
})
startPolling()
Additional note
The Claude harness does not auto-respawn dead MCP plugin child processes. So once the polling loop dies, the only recovery is restarting the entire Claude session. The reconnect patch above keeps the bot alive without requiring a session restart.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗