Telegram image files sent as documents misrouted
NousResearch/hermes-agent · cluster 18620 · gateway
Data as of
Nothing open on GitHub. Fix merged in #28519. Check it covers your case.
The short answer
- Known?
- Yes. 7 related items grouped here, 2 issues already closed.
- Fix event
- A fix was merged to main in PR #28519. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
unresolved. That is separate from the fix event. - Still open
- Nothing open on GitHub.
A bug where image files (PNG, JPG, WebP, GIF) sent as Telegram documents were rejected or mishandled instead of being routed through image/vision handling. Multiple fix attempts address routing these document-type images correctly.
Open issues0
Open PRs0
Fixes on record
-
#28519 fix(telegram): route image documents (.png/.jpg/.webp/.gif) through vision pipeline
files:
gateway/platforms/base.py,gateway/platforms/telegram.py,scripts/release.py,tests/gateway/test_telegram_documents.pyShow the diff
-
gateway/platforms/base.py@@ -837,6 +837,26 @@ def cache_video_from_bytes(data: bytes, ext: str = ".mp4") -> str: } +# --------------------------------------------------------------------------- +# Image document types +# +# Image extensions that platforms may deliver as "documents" rather than +# native photo attachments (Telegram users uploading via the file picker, +# clients that wrap stickers/screenshots as files, etc.). When we see one +# of these, we route the bytes through the image cache and the normal +# vision/photo handling path instead of rejecting them as unsupported +# documents. +# --------------------------------------------------------------------------- + +SUPPORTED_IMAGE_DOCUMENT_TYPES = { + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".png": "image/png", + ".webp": "image/webp", + ".gif": "image/gif", +} + + def get_document_cache_dir() -> Path: """Return the document cache directory, creating it if it doesn't exist.""" DOCUMENT_CACHE_DIR.mkdir(parents=True, exist_ok=True) -
gateway/platforms/telegram.py@@ -76,6 +76,7 @@ class _MockContextTypes: resolve_proxy_url, SUPPORTED_VIDEO_TYPES, SUPPORTED_DOCUMENT_TYPES, + SUPPORTED_IMAGE_DOCUMENT_TYPES, utf16_len, ) from gateway.platforms.telegram_network import ( @@ -4624,6 +4625,14 @@ async def _handle_media_message(self, update: Update, context: ContextTypes.DEFA video_mime_to_ext = {v: k for k, v in SUPPORTED_VIDEO_TYPES.items()} ext = video_mime_to_ext.get(doc.mime_type, "") + if not ext and doc.mime_type: + # SUPPORTED_IMAGE_DOCUMENT_TYPES has duplicate values (.jpg + .jpeg + # both map to image/jpeg); keep the first ext we encounter. + image_mime_to_ext: dict[str, str] = {} + for _ext, _mime in SUPPORTED_IMAGE_DOCUMENT_TYPES.items(): + image_mime_to_ext.setdefault(_mime, _ext) + ext = image_mime_to_ext.get(doc.mime_type, "") + if ext in SUPPORTED_VIDEO_TYPES: file_obj = await doc.get_file() video_bytes = await file_obj.download_as_bytearray() @@ -4635,6 +4644,21 @@ async def _handle_media_message(self, update: Update, context: ContextTypes.DEFA await self.handle_message(event) return + if ext in SUPPORTED_IMAGE_DOCUMENT_TYPES: + file_obj = await doc.get_file() + image_bytes = await file_obj.download_as_bytearray() + cached_path = cache_image_from_bytes(bytes(image_bytes), ext=ext) + event.media_urls = [cached_path] + event.media_types = [SUPPORTED_IMAGE_DOCUMENT_TYPES[ext]] + event.message_type = MessageType.PHOTO + logger.info("[Telegram] Cached user image document at %s", cached_path) + media_group_id = getattr(msg, "media_group_id", None) + if media_group_id: + await self._queue_media_group_event(str(media_group_id), event) + else: + await self.handle_message(event) + return + # Check if supported if ext not in SUPPORTED_DOCUMENT_TYPES: supported_list = ", ".join(sorted(SUPPORTED_DOCUMENT_TYPES.keys())) -
scripts/release.py@@ -179,6 +179,7 @@ "[redacted:email]": "kunci115", # PR #27098 salvage (thread-not-found retry) "[redacted:email]": "chromalinx", # PR #27014 salvage (commands for groups+DM) "[redacted:email]": "booker1207", # PR #25132 salvage (gate profile bots by allowed topics) + "[redacted:email]": "kiranvk-2011", # PR #24815 salvage (image documents → vision) "[redacted:email]": "eliteworkstation94-ai", # PR #28157 salvage (group reply session splits) "[redacted:email]": "hllqkb", "[redacted:email]": "Bongulielmi", -
tests/gateway/test_telegram_documents.py@@ -134,6 +134,11 @@ def adapter(): a = TelegramAdapter(config) # Capture events instead of processing them a.handle_message = AsyncMock() + # After PR #28494 made the empty-allowlist callback auth fail-closed + # (and #28492 wired _is_callback_user_authorized into _should_process_message), + # document-routing tests need to bypass the new gate so messages from fake + # senders reach handle_message. + a._is_callback_user_authorized = lambda user_id, **_kw: True return a
-
4 PRs closed without merging
From the close comments: done elsewhere 3 · merged via another change 1
-
#16710 fix(telegram): treat image documents (PNG/JPG/WebP/GIF) as images · done elsewhere →
77c4675,#18620,#28519 -
#20147 fix(telegram): route image documents (.webp, .png, .jpg, .gif) through image handling (#20128) · done elsewhere →
77c4675,#20128,#16710 -
#20756 fix(gateway): route image documents through vision pipeline in Telegram · done elsewhere →
77c4675,#20128 -
#24815 fix(telegram): route image documents (.png/.jpg/.webp/.gif) through vision pipeline · merged via another change →
#28519
Closed issues · 2
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.35: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- gateway
- Merged PRs
- #28519
- Closed issues
- 2
- Attempts
- 4 PRs closed without merging
- Fix link checked
- 19 May 2026