Summary
Telegram photo messages are always assigned bodyText = "<media:image>" in the inbound body builder, even when the actual contentType of the downloaded media is not image/*. This causes a mismatch between the text envelope seen by the model and the real media payload, leading to hallucinations and unreliable vision behavior.
Root cause
Two independent issues in the Telegram inbound pipeline:
1. bot-Ch7__EHu.js — unconditional <media:image> for any non-audio media
// BEFORE (buggy)
if (!bodyText && allMedia.length > 0)
if (hasAudio) bodyText = preflightTranscript || '<media:audio>';
else bodyText = `<media:image>${allMedia.length > 1 ? ` (${allMedia.length} images)` : ''}`;
Any non-audio attachment unconditionally becomes <media:image> in the body text, without checking contentType or mediaKindFromMime. If the actual media payload resolves to document or unknown downstream, the model receives contradictory signals.
2. delivery-AYrG1NE_.js — msg.photo has no explicit mimeType
function resolveMediaMetadata(msg) {
return {
fileRef: msg.photo?.[msg.photo.length - 1] ?? msg.video ?? ...,
mimeType: msg.audio?.mime_type ?? msg.voice?.mime_type ?? msg.video?.mime_type
?? msg.document?.mime_type ?? msg.animation?.mime_type
// ^^^ msg.photo has no mime_type field in Telegram API — not handled here
};
}
Telegram photo objects don't carry a mime_type field. Without an explicit fallback to "image/jpeg", the pipeline relies entirely on post-download MIME sniffing. If sniffing returns undefined or application/octet-stream, mediaKindFromMime returns undefined, which downstream treats as "unknown" → "document".
Impact
- Model receives
<media:image> in body text but no valid image input in the multimodal payload
- Results in hallucinations, incorrect descriptions, or silent failures on Telegram photo messages
- Intermittent / hard to reproduce because MIME sniffing usually succeeds for valid JPEGs, but fails under certain conditions (network issues during download, edge cases in
file-type detection, etc.)
Fix
Fix 1 — build bodyText from actual contentType:
if (!bodyText && allMedia.length > 0)
if (hasAudio) bodyText = preflightTranscript || '<media:audio>';
else {
const allImages = allMedia.every((m) => m.contentType?.startsWith('image/'));
const kind = allImages ? 'image' : 'document';
bodyText = `<media:${kind}>${allMedia.length > 1 ? ` (${allMedia.length} ${allImages ? 'images' : 'attachments'})` : ''}`;
}
Fix 2 — explicit mimeType fallback for msg.photo:
mimeType: msg.audio?.mime_type ?? msg.voice?.mime_type ?? msg.video?.mime_type
?? msg.document?.mime_type ?? msg.animation?.mime_type
?? (Array.isArray(msg.photo) && msg.photo.length > 0 ? 'image/jpeg' : void 0)
Environment
- OpenClaw version: 2026.4.15
- Channel: Telegram
- Files:
dist/extensions/telegram/bot-Ch7__EHu.js, dist/extensions/telegram/delivery-AYrG1NE_.js
Summary
Telegram
photomessages are always assignedbodyText = "<media:image>"in the inbound body builder, even when the actualcontentTypeof the downloaded media is notimage/*. This causes a mismatch between the text envelope seen by the model and the real media payload, leading to hallucinations and unreliable vision behavior.Root cause
Two independent issues in the Telegram inbound pipeline:
1.
bot-Ch7__EHu.js— unconditional<media:image>for any non-audio mediaAny non-audio attachment unconditionally becomes
<media:image>in the body text, without checkingcontentTypeormediaKindFromMime. If the actual media payload resolves todocumentorunknowndownstream, the model receives contradictory signals.2.
delivery-AYrG1NE_.js—msg.photohas no explicitmimeTypeTelegram
photoobjects don't carry amime_typefield. Without an explicit fallback to"image/jpeg", the pipeline relies entirely on post-download MIME sniffing. If sniffing returnsundefinedorapplication/octet-stream,mediaKindFromMimereturnsundefined, which downstream treats as"unknown"→"document".Impact
<media:image>in body text but no valid image input in the multimodal payloadfile-typedetection, etc.)Fix
Fix 1 — build
bodyTextfrom actualcontentType:Fix 2 — explicit
mimeTypefallback formsg.photo:Environment
dist/extensions/telegram/bot-Ch7__EHu.js,dist/extensions/telegram/delivery-AYrG1NE_.js