Bug Description
The Telegram plugin's polling loop (server.ts, lines 959-993) only retries on 409 Conflict errors. Any other error (network errors like ECONNRESET, ETIMEDOUT, DNS failures, etc.) causes the polling loop to return permanently, killing Telegram connectivity for the rest of the session.
Steps to Reproduce
- Start a Claude Code session with the Telegram plugin (
--channels plugin:telegram)
- Verify Telegram messaging works
- Change the Mac's network route (e.g., switch from USB tethering to LAN adapter, or change Wi-Fi networks)
- The
getUpdates long-poll request fails with a network error
- Expected: Polling retries with backoff and recovers
- Actual: Polling loop exits permanently; Telegram is dead for the rest of the session
Root Cause
// server.ts, lines 977-993
} catch (err) {
if (err instanceof GrammyError && err.error_code === 409) {
// Only 409 retries ✅
continue
}
if (err instanceof Error && err.message === 'Aborted delay') return
process.stderr.write(`telegram channel: polling failed: ${err}\n`)
return // ← All other errors permanently exit the loop ❌
}
Impact
Users who switch network interfaces (e.g., VPN on/off, tethering mode changes, Wi-Fi roaming) lose Telegram connectivity permanently. The Claude Code session itself recovers, but the Telegram channel is dead. The only workaround is restarting the entire session, losing all conversation context.
Suggested Fix
Add retry-with-backoff for non-409 errors (similar to the existing 409 retry logic), with a maximum retry count to prevent infinite loops on fatal errors:
} catch (err) {
if (err instanceof GrammyError && err.error_code === 409) {
// existing 409 retry logic...
continue
}
if (err instanceof Error && err.message === 'Aborted delay') return
// Network errors — retry with backoff
const MAX_NET_RETRIES = 30
if (attempt <= MAX_NET_RETRIES) {
const delay = Math.min(2000 * attempt, 30000)
process.stderr.write(
`telegram channel: polling failed (attempt ${attempt}/${MAX_NET_RETRIES}), retrying in ${delay / 1000}s: ${err}\n`,
)
await new Promise(r => setTimeout(r, delay))
continue
}
process.stderr.write(`telegram channel: polling failed after ${MAX_NET_RETRIES} retries, giving up: ${err}\n`)
return
}
Environment
- Claude Code with
plugin:telegram@claude-plugins-official v0.0.4
- grammy ^1.21.0
- macOS (Darwin 25.3.0)
- Network change trigger: StealthTether USB tethering mode switch
🤖 Generated with Claude Code
Bug Description
The Telegram plugin's polling loop (
server.ts, lines 959-993) only retries on409 Conflicterrors. Any other error (network errors likeECONNRESET,ETIMEDOUT, DNS failures, etc.) causes the polling loop toreturnpermanently, killing Telegram connectivity for the rest of the session.Steps to Reproduce
--channels plugin:telegram)getUpdateslong-poll request fails with a network errorRoot Cause
Impact
Users who switch network interfaces (e.g., VPN on/off, tethering mode changes, Wi-Fi roaming) lose Telegram connectivity permanently. The Claude Code session itself recovers, but the Telegram channel is dead. The only workaround is restarting the entire session, losing all conversation context.
Suggested Fix
Add retry-with-backoff for non-409 errors (similar to the existing 409 retry logic), with a maximum retry count to prevent infinite loops on fatal errors:
Environment
plugin:telegram@claude-plugins-officialv0.0.4🤖 Generated with Claude Code