Skip to content

fix(telegram): harden photo download against crash scenarios#980

Open
snemesh wants to merge 1 commit intoanthropics:mainfrom
snemesh:fix/telegram-photo-crash-resilience
Open

fix(telegram): harden photo download against crash scenarios#980
snemesh wants to merge 1 commit intoanthropics:mainfrom
snemesh:fix/telegram-photo-crash-resilience

Conversation

@snemesh
Copy link
Copy Markdown

@snemesh snemesh commented Mar 25, 2026

Problem

Sending a photo to the Telegram bot can crash the channel process, making it completely unresponsive until restarted (#944). The photo download callback in message:photo handler has three gaps:

  1. No empty array guard — if ctx.message.photo is empty, photos[photos.length - 1] is undefined and .file_id throws a TypeError that propagates as an unhandled error
  2. No HTTP status check — if the Telegram file API returns 4xx/5xx, res.arrayBuffer() reads an error body that gets written to disk as a corrupt JPEG
  3. No size limit — without a cap, a large file response could cause memory pressure

Fix

All three cases now return undefined (graceful degradation) instead of crashing. The message is still delivered to Claude without the image attachment, and errors are logged to stderr.

Changes

  • external_plugins/telegram/server.ts — 10 insertions, 1 deletion

Test plan

  • bun build passes
  • 12/12 resilience tests pass — covers all crash scenarios
Test output (12/12 passed)
── Normal flow ──
  ✅ Normal photo download → /tmp/inbox/...-u1.jpg

── Crash scenario: empty photo array ──
  ✅ Empty array → no crash → undefined (graceful)
  ✅ null photos → no crash → undefined (graceful)
  ✅ undefined photos → no crash → undefined (graceful)

── Crash scenario: Telegram API edge cases ──
  ✅ No file_path → graceful
  ✅ getFile throws → graceful

── Crash scenario: HTTP errors ──
  ✅ HTTP 404 → graceful
  ✅ HTTP 500 → graceful
  ✅ fetch failed → graceful

── Crash scenario: resource limits ──
  ✅ 60MB photo → rejected gracefully
  ✅ arrayBuffer() throws → graceful

── Normal flow: multiple sizes ──
  ✅ Picks largest (last) from array

═══ Result: 12/12 passed ✅ ═══

Fixes #944

The photo download callback in message:photo handler has three gaps
that can crash the channel process or silently corrupt state:

1. No guard for empty photo array — if ctx.message.photo is empty,
   photos[photos.length - 1] is undefined and .file_id throws a
   TypeError that propagates up as an unhandled error.

2. No HTTP status check — if the Telegram file API returns 4xx/5xx,
   res.arrayBuffer() reads an error page into a Buffer that gets
   written to disk as a corrupt file.

3. No size limit — the largest photo variant can be up to 20MB;
   without a cap, a very large response could cause memory pressure
   in constrained environments.

All three return undefined on failure (graceful degradation) instead
of crashing the process. The message is still delivered to Claude
without the image attachment.

Fixes anthropics#944
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Telegram plugin: receiving photos crashes the channel, blocks all subsequent messages

1 participant