Bug Description
Slack image attachments received through the gateway can be downloaded as a Slack HTML sign-in / redirect page and then cached locally with a .png/.jpg extension. Hermes later surfaces that cached path to the agent as if it were a real image, but vision_analyze eventually rejects it with Only real image files are supported for vision analysis.
This turns an upstream Slack media download/auth/access failure into a confusing downstream vision failure.
Steps to Reproduce
- Run Hermes with the Slack gateway enabled.
- In a Slack channel/thread where Hermes is active, mention the bot and attach an image.
- Ask Hermes to inspect/read the image (or rely on the normal image-analysis path).
- In failing cases, inspect the cached file under
~/.hermes/cache/images/ (or legacy ~/.hermes/image_cache/).
- Observe that the cached
*.png/*.jpg file is actually HTML, and later vision_analyze fails.
Minimal evidence from a real repro:
$ file /Users/frog/.hermes/image_cache/img_244acf0cbbfe.png
/Users/frog/.hermes/image_cache/img_244acf0cbbfe.png: HTML document text, ASCII text, with very long lines (28115)
The cached file begins with <!DOCTYPE html> and has <title>Slack</title>.
Expected Behavior
If Slack media download fails or returns HTML / non-image bytes, Hermes should:
- reject the download immediately,
- log a clear Slack download/auth/access error,
- avoid caching the response as an image,
- and avoid handing the agent a bogus local image path.
Actual Behavior
Hermes caches arbitrary response bytes as an image file and only fails later, when vision_analyze performs magic-byte validation and returns:
Error analyzing image: Only real image files are supported for vision analysis.
Affected Component
- Gateway (Telegram/Discord/Slack/WhatsApp)
- Tools (terminal, file ops, web, code execution, etc.)
Messaging Platform (if gateway-related)
Operating System
macOS 13.7.8
Python Version
3.11.15
Hermes Version
v0.8.0 (2026.4.8)
Relevant Logs / Traceback
vision_analyze -> Error analyzing image: Only real image files are supported for vision analysis.
$ file /Users/frog/.hermes/image_cache/img_244acf0cbbfe.png
HTML document text, ASCII text, with very long lines (28115)
Root Cause Analysis (optional)
Current Slack image handling appears to accept the response body as image bytes without validating that it is actually an image:
gateway/platforms/slack.py:874-882 routes Slack image/* attachments into _download_slack_file(...)
gateway/platforms/slack.py:1299-1321 performs an authenticated GET and then immediately calls cache_image_from_bytes(response.content, ext)
gateway/platforms/base.py:95-110 blindly writes those bytes to disk
tools/vision_tools.py:102-121 and 355-357 later detect that the cached file is not a real image and reject it
So even if the underlying trigger is Slack auth/scope/access/redirect behavior, Hermes currently converts that upstream failure into a misleading downstream vision error instead of failing at the Slack download boundary.
Related external reports show the same Slack symptom (HTML sign-in page instead of file bytes):
Proposed Fix (optional)
- Validate Slack download responses before caching them as images.
- Reject
text/html responses.
- Also validate image magic bytes (not just extension / Slack metadata) before
cache_image_from_bytes(...).
- Return/log an explicit Slack media download error when the response is HTML or otherwise not an image.
- Add a regression test that simulates
200 OK + HTML body from a Slack file URL and asserts Hermes does not cache it as an image.
There are already retry-path tests for Slack media download, but I did not find a regression test for the HTTP 200 but body is HTML login page case.
Bug Description
Slack image attachments received through the gateway can be downloaded as a Slack HTML sign-in / redirect page and then cached locally with a
.png/.jpgextension. Hermes later surfaces that cached path to the agent as if it were a real image, butvision_analyzeeventually rejects it withOnly real image files are supported for vision analysis.This turns an upstream Slack media download/auth/access failure into a confusing downstream vision failure.
Steps to Reproduce
~/.hermes/cache/images/(or legacy~/.hermes/image_cache/).*.png/*.jpgfile is actually HTML, and latervision_analyzefails.Minimal evidence from a real repro:
The cached file begins with
<!DOCTYPE html>and has<title>Slack</title>.Expected Behavior
If Slack media download fails or returns HTML / non-image bytes, Hermes should:
Actual Behavior
Hermes caches arbitrary response bytes as an image file and only fails later, when
vision_analyzeperforms magic-byte validation and returns:Error analyzing image: Only real image files are supported for vision analysis.Affected Component
Messaging Platform (if gateway-related)
Operating System
macOS 13.7.8
Python Version
3.11.15
Hermes Version
v0.8.0 (2026.4.8)
Relevant Logs / Traceback
Root Cause Analysis (optional)
Current Slack image handling appears to accept the response body as image bytes without validating that it is actually an image:
gateway/platforms/slack.py:874-882routes Slackimage/*attachments into_download_slack_file(...)gateway/platforms/slack.py:1299-1321performs an authenticated GET and then immediately callscache_image_from_bytes(response.content, ext)gateway/platforms/base.py:95-110blindly writes those bytes to disktools/vision_tools.py:102-121and355-357later detect that the cached file is not a real image and reject itSo even if the underlying trigger is Slack auth/scope/access/redirect behavior, Hermes currently converts that upstream failure into a misleading downstream vision error instead of failing at the Slack download boundary.
Related external reports show the same Slack symptom (HTML sign-in page instead of file bytes):
Proposed Fix (optional)
text/htmlresponses.cache_image_from_bytes(...).200 OK+ HTML body from a Slack file URL and asserts Hermes does not cache it as an image.There are already retry-path tests for Slack media download, but I did not find a regression test for the
HTTP 200 but body is HTML login pagecase.