[BUG] `telegram` plugin (claude-plugins-official) — frequent poller crashes, `bun` launch failures, and silent inbound drop
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Bug report: telegram plugin (claude-plugins-official) — frequent poller crashes, bun launch failures, and silent inbound drop
Filed: 2026-05-29
Reporter: Karl Zesewitz (karl.zesewitz@googlemail.com)
Suggested venue: https://github.com/anthropics/claude-code/issues (marketplace owner = Anthropic, support@anthropic.com)
---
Environment
| | |
|---|---|
| Claude Code | 2.1.157 |
| OS | macOS (Darwin 25.3.0), Apple Silicon |
| Plugin | telegram@claude-plugins-official |
| Plugin version | inconsistent — .claude-plugin/plugin.json says 0.0.6, package.json says 0.0.1, MCP handshake reports serverVersion {"name":"telegram","version":"1.0.0"} |
| Runtime | bun (~/.bun/bin/bun), grammy-based server.ts |
| Launch | .mcp.json → command: "bun", args: ["run","--cwd","${CLAUDE_PLUGIN_ROOT}","--shell=bun","--silent","start"] |
| Usage | Long-running claude --channels plugin:telegram@claude-plugins-official session as a personal assistant bridge |
---
Summary
Since the most recent plugin refresh, the Telegram bridge is unstable in three distinct, independently reproducible ways. The user experience is: the plugin shows as connected in /mcp, but inbound messages do not arrive, and the poller process crashes — sometimes after a single message. Evidence is drawn from the plugin's own MCP logs across multiple working directories.
---
Bug 1 — MCP server fails to launch: Executable not found in $PATH: "bun" (15×)
Symptom. The MCP server intermittently fails to start; /mcp then shows the server failed/disconnected, and there is no poller at all → zero inbound.
Evidence (mcp-logs-plugin-telegram-telegram, cwd ~/DEV/Your OS):
"error":"Connection failed: Executable not found in $PATH: \"bun\"" ← 15 occurrences
Root cause. .mcp.json launches the server with the bare command "bun", relying on bun being on the spawned process's PATH. When Claude Code is started from a context whose PATH does not include ~/.bun/bin (launchd/cron agents, restricted login shells, GUI-launched sessions), the spawn fails outright. bun is installed and on PATH for interactive shells, which is why it works sometimes and not others — a classic PATH-dependent flake.
Expected. The server should launch deterministically regardless of the parent PATH.
Suggested fix. Resolve an absolute interpreter path (e.g. probe ~/.bun/bin/bun, /opt/homebrew/bin/bun, which bun at install time and pin it), or ship a small launcher shim that sources the user's bun path, or document a hard PATH requirement and fail with an actionable message instead of a bare "not found".
---
Bug 2 — Poller goes stale / crashes and orphans processes: replacing stale poller (28×)
Symptom. The polling process dies or goes stale (Karl reports: sometimes right after a single inbound message). A new session detects and replaces it, but the dead bun server.ts children are left orphaned (reparented to PID 1) and accumulate.
Evidence.
"Server stderr: telegram channel: replacing stale poller pid=27815" (2026-05-07)
"... replacing stale poller pid=76540" (2026-05-11)
"... replacing stale poller pid=6255" (2026-05-14)
"... replacing stale poller pid=28428" (2026-05-24)
… 28 such events total across cwds (24 in ~/DEV/Your OS alone),
recurring almost daily through 2026-05-29.
Direct process evidence (2026-05-29): 3 orphaned bun server.ts processes, parent PID = 1 (launchd), 1+ day old, holding no active Telegram connection, alongside the one live poller. The plugin's "replace stale poller" path recovers polling but does not reap the dead child.
Expected. A crashed/replaced poller should be terminated and reaped; no orphan accumulation.
Suggested fix. On "replacing stale poller", SIGTERM/SIGKILL the old PID and its bun subtree (and/or register a process.on('exit'/'SIGTERM') cleanup in server.ts). Investigate why the poller goes stale after a message — likely an unhandled rejection / dropped long-poll connection in the grammy getUpdates loop that exits the worker without exiting the process.
---
Bug 3 — "Connected" in /mcp but inbound is silently dropped (misleading status + debug-only log)
Symptom. /mcp reports the telegram server as connected/online (because the MCP tool transport — used for outbound reply — is up), yet inbound messages never reach the agent. There is no user-visible signal that inbound is being discarded.
Evidence.
"debug":"Channel notifications skipped: server plugin:telegram:telegram not in --channels list for this session" ← 10× (debug level only)
Outbound reply works in the same session (confirmed: messages sent, Bot-API returned message IDs), which makes the asymmetry especially confusing — sending works, receiving silently does not.
Root cause (partly by design, but the UX is the bug). A session that did not pass --channels plugin:telegram@... has its inbound channel notifications dropped by the host gate. That requirement is reasonable, but: (a) it is only logged at debug, (b) /mcp still shows "connected", and (c) there is no warning anywhere the user looks. Net effect: the user sees "online" and reasonably concludes inbound should work.
Expected. When a telegram server is connected but the session is not subscribed via --channels, surface a visible warning (in /mcp status and/or at startup): "Telegram connected for outbound only — inbound disabled because this session was not started with --channels."
Suggested fix. Promote the "notifications skipped" condition from debug to a one-time visible warning, and annotate the server's /mcp status line with an "outbound-only / inbound-disabled" badge when the --channels subscription is missing.
---
Impact
A personal-assistant bridge that silently stops receiving messages — while reporting itself online — is worse than one that's visibly down: the user keeps messaging into a void. Combined with the PATH-flaky launch (Bug 1) and orphan-leaking crashes (Bug 2), the bridge cannot be relied on for always-on use, which is its core purpose.
Minimal repro
- Start
claude --channels plugin:telegram@claude-plugins-officialfrom a GUI/launchd context whose PATH lacks~/.bun/bin→ Bug 1 (server fails to launch). - With a working poller, send several inbound messages over hours/days → Bug 2 (stale-poller replacement + orphaned bun processes; observe with
pgrep -fl "bun server.ts"→ parents at PID 1). - Start
claudewithout--channelsbut with the plugin enabled;/mcpshows telegram connected; send an inbound message → never arrives (Bug 3). Outboundreplystill works.
Attachments to include when filing
~/Library/Caches/claude-cli-nodejs/-Users-karl-DEV-Your-OS/mcp-logs-plugin-telegram-telegram/*.jsonl(redact bot token / chat IDs)- Output of
pgrep -fl "bun server.ts"andps -o pid,ppid,etime -p <pids>showing orphans at PID 1
What Should Happen?
Plgin crasche after one or two inbound messages
Error Messages/Logs
is atteched written by claude code opus 4.8
Steps to Reproduce
see above
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
2.1.153
Claude Code Version
2.1.157
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗