-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Bug Description
Photos sent via Telegram are downloaded and base64-encoded correctly, but the media_type is set to application/octet-stream instead of the actual image type (e.g. image/jpeg). This causes LLM providers to reject the image content, as they require a valid image MIME type.
Regression
This was supposed to be fixed as part of issue #362 and the related PR #365. The Telegram parsing and bridge download pipeline was added, but the media type detection has a bug that silently breaks vision.
Root Cause
In crates/openfang-channels/src/bridge.rs, download_image_to_blocks() (line ~818):
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.map(|ct| ct.split(';').next().unwrap_or(ct).trim().to_string());
let media_type = content_type.unwrap_or_else(|| {
// fallback to URL extension detection
...
});The code trusts the Content-Type header from Telegram's file download API. However, Telegram returns application/octet-stream for all file downloads via getFile. Since the header IS present (just wrong), the URL-extension fallback never runs.
The result: ContentBlock::Image { media_type: "application/octet-stream", data: "..." } is sent to the LLM, which rejects it because application/octet-stream is not a valid image MIME type.
Evidence
Session logs show: [image: application/octet-stream] — confirming the image data arrives but with wrong MIME type.
Proposed Fix
- If
Content-Typeisapplication/octet-streamor another non-image type, fall through to secondary detection - Add magic-byte detection (JPEG
FF D8, PNG89 50 4E 47, etc.) as the most reliable method - Keep URL extension as tertiary fallback
Environment
- OpenFang v0.3.46
- Channel: Telegram (polling mode)
- LLM: qwen-plus (OpenAI-compatible API)
Related
- Telegram bridge: incoming photos/media are silently dropped #362 — Original issue (Telegram photos silently dropped)
- PR feat(telegram): support incoming photos, documents, voice and location #365 — My original PR implementing incoming media support (closed without merge)