Telegram channel plugin 0.0.6: polling never starts under plugin runtime (repro across Claude 2.1.207-2.1.210 + Bun 1.3.11/1.3.14; standalone works) — follow-up to locked #36606

Status Fixed / completed
Reported on v2.1.207
Maintainer reply None cached
Activity 3 comments · opened Jul 15, 2026 · closed Jul 15, 2026

Same bug as the (locked) #36606, reproduced on plugin 0.0.6 with new elimination data that narrows the cause to the plugin runtime's spawn context.

Reproduced on plugin 0.0.6 (so the all-errors retry loop that 0.0.6 added does not cover this) with extensive elimination testing. Windows 11 Pro 10.0.26200, native CLI install.

Same fingerprint: server process alive, MCP tools work, Channel notifications registered in the client log — but grammY polling never starts: no polling as @<bot> stderr line, no retry/error lines, and the bot's getUpdates queue grows unboundedly (getWebhookInfo.pending_update_count stuck at 18 for hours). A one-shot external getUpdates probe (no offset) returns data instantly instead of 409 — nothing is holding a long-poll, so bot.start() dies before its first successful getUpdates.

Eliminated (each tested tonight):

  • Claude Code version: identical behavior on 2.1.207, 2.1.209, 2.1.210 (fresh server spawn each; auto-updater disabled during the bisect).
  • Bun version: identical on Bun 1.3.11 and 1.3.14.
  • Machine/network/env: standalone bun -e "fetch('https://api.telegram.org')" → 200 in <1s; standalone grammY new Bot(token); await bot.init() from the plugin directory → init OK in 430 ms; no *_PROXY/NODE_OPTIONS env in the session environment Claude propagates to children.
  • Config gates: bot is a group member, privacy mode disabled (getMe.can_read_all_group_messages: true), session launched with --channels plugin:telegram@claude-plugins-official, access.json valid.

One consistent oddity worth a look: ~30 s after every spawn the client log shows
notifications/claude/channel/permission: <5-char-id> → allow (matched pending) — the permission handshake completes, yet polling still never begins. The dead server also holds 2-3 ESTABLISHED but idle TCP connections to api.telegram.org:443 (149.154.166.110 + the IPv6 endpoint), which looks like fetch requests that were sent (or half-sent) and never complete — consistent with bot.init()/getUpdates hanging forever inside the plugin-spawned process specifically (grammY has no default request timeout, so a hung fetch produces exactly this silent no-error state).

Since it reproduces across Claude versions and Bun versions but never standalone, the delta seems to be the plugin runtime's spawn context (stdio wiring / bun run --silent start wrapper) rather than the plugin code, Bun, or the network. Happy to run diagnostics on a debug build if useful.

View original on GitHub ↗

3 Comments

github-actions[bot] · 3 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/36606
  2. https://github.com/anthropics/claude-code/issues/67792
  3. https://github.com/anthropics/claude-code/issues/55841

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

blurxy · 3 months ago

RESOLVED — root cause found on our machine, and it was NOT a Claude Code bug. Closing.

A stale user-level TELEGRAM_BOT_TOKEN environment variable (holding a DIFFERENT bot's token — our trading bot's alerts bot) was inherited by Claude Code and passed to the plugin MCP server. Per the plugin's documented precedence, shell env beats ~/.claude/channels/telegram/.env — so the plugin was silently running as the wrong bot the whole time:

  • Inbound "polling never starts": the plugin polled the alerts bot's token, which already had a getUpdates consumer (our own daemon) → the plugin lost the 409 conflict war and gave up after 8 attempts (per 0.0.6's retry loop), on every spawn, on every Claude/Bun version. That's why it looked version-independent and never reproduced standalone (standalone tests read the .env file → correct token).
  • The tell that broke the case: an outbound reply tool call landed in the WRONG bot's chat.
  • Fix: delete the env var, relaunch Claude Code → clean env → plugin reads the file token.

Suggestion for the plugin (would have saved us a full night): log which token source was used (env vs file) at startup, and/or warn when a shell TELEGRAM_BOT_TOKEN overrides a present .env file — the override is silent and the resulting symptom (deaf bot, working outbound) points everywhere except the token. Exposing poller status (last getUpdates result / 409 counter) through a tool would also make this diagnosable in minutes.

The original locked #36606 may be worth re-examining through this lens — same fingerprint can be produced by any second consumer on the token, not just a runtime bug.

github-actions[bot] · 1 month ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.