hermes - ✅(Solved) Fix [Telegram gateway] Unsupported document types are sent to agent as fake user messages; cache failures silently lose the attachment [4 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#23045Fetched 2026-05-11 03:31:38
View on GitHub
Comments
0
Participants
1
Timeline
8
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×4labeled ×4

Two related bugs in gateway/platforms/telegram.py cause Telegram document attachments to silently fail or, worse, get mistakenly delivered to the agent as if the user typed the gateway's own error string. Both are in the document-handling block at roughly lines 3258-3322 of telegram.py (current main).

Error Message

Download and cache

file_obj = await doc.get_file() doc_bytes = await file_obj.download_as_bytearray() raw_bytes = bytes(doc_bytes) cached_path = cache_document_from_bytes(raw_bytes, original_filename or f"document{ext}") mime_type = SUPPORTED_DOCUMENT_TYPES[ext] event.media_urls = [cached_path] event.media_types = [mime_type] logger.info("[Telegram] Cached user document at %s", cached_path)

For text files, inject content into event.text (capped at 100 KB)

... text injection block ...

except Exception as e: logger.warning("[Telegram] Failed to cache document: %s", e, exc_info=True)

Root Cause

The agent then went in circles asking "where is the file?" because it had no signal that an attempt-to-attach had occurred at all — only a string that looked like the user complaining about an unsupported type.

Fix Action

Fixed

PR fix notes

PR #23061: fix(gateway): Telegram unsupported doc type notifies user directly; cache failure bails early (#23045)

Description (problem / solution / changelog)

Summary

Fixes two bugs reported in #23045 in gateway/platforms/telegram.py.


Bug 1: Unsupported document types injected into agent pipeline as fake user messages

Root cause — When a user sends an unsupported file (e.g. .epub), the handler set event.text to a gateway-generated error string and called handle_message(event). The agent received a turn that looked exactly like the user had typed "Unsupported document type '.epub'..." — with no metadata indicating it was gateway-generated, not user content.

Impact — The agent couldn't tell an attachment attempt had occurred, went in circles asking "where is the file?", and produced confused responses as documented in the issue.

Fix — Use msg.reply_text() to send the error notice back to the user directly, then return without touching the agent pipeline. The file label (original filename) is included in the reply so the user knows which attachment was rejected.


Bug 2: Cache failures silently swallowed; broken event delivered to agent

Root cause — The except Exception block only logged the error, then let execution fall through to the handle_message call below. The agent received a MessageEvent with empty media_urls/media_types, with no signal that the document was never actually cached.

Fix — After notifying the user via reply_text, return immediately so no partial event ever reaches the agent.


Tests

  • Updated test_missing_filename_and_mime_rejected — old version asserted the old (buggy) error-string-in-agent behaviour; now asserts handle_message is NOT called and reply_text IS called.
  • Updated test_download_exception_handled → renamed test_download_exception_notifies_user_not_agent — old version asserted handle_message was still called after a download failure; now asserts the opposite.
  • Added test_unsupported_type_notifies_user_not_agent — explicit .epub test confirming the pipeline is never entered.

All 42 tests in test_telegram_documents.py pass.

Changed files

  • gateway/platforms/telegram.py (modified, +26/-5)
  • scripts/release.py (modified, +1/-0)
  • tests/gateway/test_telegram_documents.py (modified, +29/-6)
  • tools/process_registry.py (modified, +1/-1)

PR #23063: fix: keep telegram document failures out of agent input

Description (problem / solution / changelog)

Summary

  • Reply in Telegram for unsupported document types instead of forging gateway error text as agent input.
  • Reply in Telegram when document download/cache fails, then stop instead of forwarding an empty/broken event.
  • Add regressions for unsupported document rejection and cache/download failure visibility.

Closes #23045

Test Plan

  • scripts/run_tests.sh tests/gateway/test_telegram_documents.py -q
  • scripts/run_tests.sh tests/gateway/test_telegram_documents.py tests/gateway/test_telegram_photo_interrupts.py tests/gateway/test_telegram_group_gating.py -q

Changed files

  • gateway/platforms/telegram.py (modified, +27/-4)
  • tests/gateway/test_telegram_documents.py (modified, +44/-6)

PR #23241: fix(telegram): route unsupported docs and cache errors to user, not agent

Description (problem / solution / changelog)

Summary

Fixes two bugs in Telegram document handling where errors are incorrectly routed into the agent pipeline instead of being delivered directly to the user.

Bug 1 — Unsupported document types

When a user sends an unsupported file (e.g. .epub), the gateway was setting event.text to an error message and calling handle_message(), making the agent think the user typed "Unsupported document type '.epub'..." as a message. The agent then goes in circles trying to help with a file it never received.

Fix: Send the error directly to the user via update.message.reply_text() and return early — the agent never sees it.

Bug 2 — Cache failures silently lose attachments

When document download/caching fails (e.g. httpx.ConnectError to Telegram CDN), the broad except Exception handler only logged a warning and fell through to handle_message() with an empty event — no media, no text, no signal that an attachment was attempted. The user thinks the file was delivered; the agent thinks nothing happened.

Fix: Reply to the user with the error and return. The user knows the download failed and can retry.

Additional fix

Applied the same direct-reply pattern to the "document too large" check (previously also routed through handle_message as a fake user message).

Files changed

  • gateway/platforms/telegram.py — 3 error paths changed from handle_message() to update.message.reply_text()
  • tests/gateway/test_telegram_documents.py — updated 5 tests to verify direct reply behavior instead of handle_message interception

Fixes #23045

X: @rojassartorio

Changed files

  • gateway/platforms/telegram.py (modified, +23/-10)
  • tests/gateway/test_telegram_documents.py (modified, +17/-9)

PR #23349: fix(telegram): reply to user on unsupported docs and cache failures

Description (problem / solution / changelog)

Stops routing unsupported document types and CDN cache download failures into the agent pipeline as fake user messages. Instead, sends a direct reply to the user and drops the event.

  • Unsupported documents: reply with the supported type list instead of forging event.text and treating it as a user message.
  • Cache/download failures: reply with an error message instead of silently swallowing the exception and sending an empty event to the agent.

Closes #23045

Changed files

  • gateway/platforms/telegram.py (modified, +12/-2)
  • scripts/release.py (modified, +1/-0)

Code Example

if ext not in SUPPORTED_DOCUMENT_TYPES:
    supported_list = ", ".join(sorted(SUPPORTED_DOCUMENT_TYPES.keys()))
    event.text = (
        f"Unsupported document type '{ext or 'unknown'}'. "
        f"Supported types: {supported_list}"
    )
    logger.info("[Telegram] Unsupported document type: %s", ext or "unknown")
    await self.handle_message(event)
    return

---

# Download and cache
file_obj = await doc.get_file()
doc_bytes = await file_obj.download_as_bytearray()
raw_bytes = bytes(doc_bytes)
cached_path = cache_document_from_bytes(raw_bytes, original_filename or f"document{ext}")
mime_type = SUPPORTED_DOCUMENT_TYPES[ext]
event.media_urls = [cached_path]
event.media_types = [mime_type]
logger.info("[Telegram] Cached user document at %s", cached_path)

# For text files, inject content into event.text (capped at 100 KB)
# ... text injection block ...

except Exception as e:
    logger.warning("[Telegram] Failed to cache document: %s", e, exc_info=True)

---

2026-05-09 23:40:01,432 INFO gateway.platforms.telegram: [Telegram] Unsupported document type: .epub
2026-05-09 23:40:02,473 INFO gateway.run: inbound message: platform=telegram user=Richard Murillo chat=8244195464 msg="Unsupported document type '.epub'. Supported types: .cfg, .csv, .js"
2026-05-09 23:49:08,615 WARNING gateway.platforms.telegram: [Telegram] Failed to cache document: httpx.ConnectError:
2026-05-09 23:50:54,871 INFO gateway.run: inbound message: platform=telegram user=Richard Murillo chat=8244195464 msg='ffs, it was attached as a .MD file'
RAW_BUFFERClick to expand / collapse

Summary

Two related bugs in gateway/platforms/telegram.py cause Telegram document attachments to silently fail or, worse, get mistakenly delivered to the agent as if the user typed the gateway's own error string. Both are in the document-handling block at roughly lines 3258-3322 of telegram.py (current main).

Bug 1: Unsupported document types are routed to the agent as fake user messages

Where

gateway/platforms/telegram.py lines ~3265-3273:

if ext not in SUPPORTED_DOCUMENT_TYPES:
    supported_list = ", ".join(sorted(SUPPORTED_DOCUMENT_TYPES.keys()))
    event.text = (
        f"Unsupported document type '{ext or 'unknown'}'. "
        f"Supported types: {supported_list}"
    )
    logger.info("[Telegram] Unsupported document type: %s", ext or "unknown")
    await self.handle_message(event)
    return

What happens

When a user sends an unsupported file (e.g. .epub):

  1. The gateway sets event.text to "Unsupported document type '.epub'. Supported types: .cfg, .csv, ..."
  2. It calls self.handle_message(event) — which routes the event into the agent pipeline as if it were a normal user message
  3. From the agent's perspective, the user just sent a message saying "Unsupported document type '.epub'..." — there is no metadata indicating this is a gateway-generated error, not user content

Observed impact

In a real Telegram session 2026-05-09, a .epub was attached. The agent received turns where inbound message: ... msg="Unsupported document type '.epub'..." appeared in gateway.log as if the user had typed it. The agent had no way to know:

  • The actual user intent was to share an attachment
  • The error was generated by the gateway, not typed by the user
  • The user's next messages ("ffs, it was attached as a .MD file") referred to a previous attempt the gateway never surfaced as anything except an error string

The agent then went in circles asking "where is the file?" because it had no signal that an attempt-to-attach had occurred at all — only a string that looked like the user complaining about an unsupported type.

Proposed fix

The user-facing message about unsupported types should be sent back to the user via the Telegram channel (a reply message), not routed into the agent pipeline. Two minimum changes:

  1. Use a Telegram reply (update.message.reply_text(...)) to inform the user, instead of forging an event.text value
  2. Either return without calling handle_message, OR call handle_message with event.text = None and set a structured flag like event.gateway_notice = "unsupported_document_type" so the agent can recognize it as a gateway-generated event distinct from user content

Bonus: include the original filename in the reply so the user knows which file got rejected when they sent multiple in close succession.


Bug 2: Cache failures are silently swallowed; agent receives an empty/broken event

Where

gateway/platforms/telegram.py lines ~3286-3315:

# Download and cache
file_obj = await doc.get_file()
doc_bytes = await file_obj.download_as_bytearray()
raw_bytes = bytes(doc_bytes)
cached_path = cache_document_from_bytes(raw_bytes, original_filename or f"document{ext}")
mime_type = SUPPORTED_DOCUMENT_TYPES[ext]
event.media_urls = [cached_path]
event.media_types = [mime_type]
logger.info("[Telegram] Cached user document at %s", cached_path)

# For text files, inject content into event.text (capped at 100 KB)
# ... text injection block ...

except Exception as e:
    logger.warning("[Telegram] Failed to cache document: %s", e, exc_info=True)

What happens

The broad except Exception (currently catching httpx.ConnectError and friends from Telegram CDN download failures) logs a warning and falls through — no return, no user-facing message, no agent-visible signal. The function then proceeds to line ~3322's await self.handle_message(event) with:

  • event.media_urls = [] (never set, since the cache call failed before line 3292)
  • event.media_types = [] (same reason)
  • event.text = whatever caption the user typed (often empty)
  • No flag indicating an attempted-but-failed attachment

Observed impact

In the same 2026-05-09 session, a .md attachment hit httpx.ConnectError at the cache step (gateway log: WARNING gateway.platforms.telegram: [Telegram] Failed to cache document: httpx.ConnectError:). The user thought the file had been delivered. The agent received an empty event with no media and no text. From there:

  • Agent had no visible signal an attachment was even attempted
  • Agent's earlier wrong claim ("Telegram doesn't deliver attachments to me") was reinforced
  • The user had to escalate frustration multiple turns before the agent stumbled onto the cache directory and root-caused the failure by reading gateway.log directly

This is a "silent data loss" bug class. The user thinks they delivered something; the agent thinks nothing happened; the only record is a warning buried in the log.

Proposed fix

Three independent improvements (any one closes the silent-loss):

  1. Send a user-facing error reply on cache failure: await update.message.reply_text(f"⚠️ Couldn't download your attachment ({e.__class__.__name__}). Please retry.") before the function returns.
  2. Retry with backoff before giving up: Telegram CDN flakes are transient; one retry with a 2-3s sleep would catch most. The httpx ConnectError observed in the affected session was a known network blip (the same gateway log shows two other ConnectErrors against api.telegram.org earlier the same day).
  3. Surface the failure to the agent as structured signal: set event.gateway_error = {"type": "document_cache_failure", "exception": str(e), "original_filename": original_filename} so the agent can react ("I see Telegram tried to deliver an attachment but the cache failed — please retry") instead of silently treating the message as content-less.

Ideally do all three: reply to the user immediately, retry once, and surface the failure as structured signal even after retry exhaustion.


Combined repro

In a Telegram chat with a Hermes gateway:

  1. Attach an unsupported file type (e.g., .epub). Observe agent receives the gateway's error text as if the user typed it.
  2. Attach a .md file during a brief network blip to api.telegram.org (or simulate by inducing httpx.ConnectError at cache step). Observe the agent receives an empty event with no signal that an attachment was attempted.

Both bugs were observed back-to-back in a real session 2026-05-09 ~23:40-23:50 PT.

Severity

Medium-high. The user-perceived effect is "the agent is broken / lost my file / pretends I didn't send anything." This is exactly the failure mode that erodes user trust in the gateway. The bugs interact: Bug 1 made the agent confused about which files the user was referencing in subsequent turns, which fed into Bug 2's silent loss because the agent had no consistent picture of what files had even been attempted.

Out of scope for this issue

  • Adding .epub to SUPPORTED_DOCUMENT_TYPES. That's a separate feature decision.
  • Restructuring MessageEvent to have a first-class gateway_notice / gateway_error field. The proposed fix can use existing event attributes; a structured-event refactor is a separate concern.
  • Other platforms (Discord, Slack, Matrix). The fixes here are Telegram-specific. Other platforms may have similar shapes worth auditing as follow-ups.

Source

Discovered during a real user session 2026-05-09. Gateway log excerpt:

2026-05-09 23:40:01,432 INFO gateway.platforms.telegram: [Telegram] Unsupported document type: .epub
2026-05-09 23:40:02,473 INFO gateway.run: inbound message: platform=telegram user=Richard Murillo chat=8244195464 msg="Unsupported document type '.epub'. Supported types: .cfg, .csv, .js"
2026-05-09 23:49:08,615 WARNING gateway.platforms.telegram: [Telegram] Failed to cache document: httpx.ConnectError:
2026-05-09 23:50:54,871 INFO gateway.run: inbound message: platform=telegram user=Richard Murillo chat=8244195464 msg='ffs, it was attached as a .MD file'

The agent's session loop spent multiple turns confused about whether attachments had been delivered, what file the user was referencing, and why earlier "messages" appeared to be from the user but contained gateway-generated error text.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix [Telegram gateway] Unsupported document types are sent to agent as fake user messages; cache failures silently lose the attachment [4 pull requests, 1 participants]