Summary
When sending multiple images as a Telegram media group (album), if one photo fails to download (network error, API timeout, file too large, etc.), it is silently dropped with no notification to the user. The AI receives fewer images than were sent, with no indication of what happened.
Version: 2026.3.23-2
Channel: Telegram
Reproduction
- Send 8 images as an album (media group) via Telegram
- One photo encounters a download error (e.g., network blip, 30s read idle timeout on a large file)
- AI responds as if only 7 images were received — user is never told one was lost
- In some cases the failed image produces a partial/corrupted file ("fragment") rather than being absent entirely
Root Cause
1. Silent skip on download failure (pi-embedded-CbCYZxIb.js, processMediaGroup)
try {
media = await resolveMedia(item.ctx, mediaMaxBytes, opts.token, telegramTransport, telegramCfg.apiRoot);
} catch (mediaErr) {
if (!isRecoverableMediaGroupError(mediaErr)) throw mediaErr;
runtime.log?.(warn(`media group: skipping photo that failed to fetch: ${String(mediaErr)}`));
continue; // ← silently skipped, user never notified
}
if (media) allMedia.push(...); // ← null also silently dropped
When resolveMedia throws a recoverable error (MediaFetchError, MediaSizeLimitError) or returns null (after getFile() exhausts 3 retries), the photo is just skipped. No error reply is sent to the user.
2. Partial download ("fragment") from idle timeout
downloadAndSaveTelegramFile uses a 30-second read idle timeout (TELEGRAM_DOWNLOAD_IDLE_TIMEOUT_MS = 30000). A large image that stalls mid-download can produce an incomplete file that gets passed to the AI as valid media.
3. Timer race condition (minor)
The media group buffer uses a 500ms flush timer (mediaGroupTimeoutMs = 500). Each incoming photo resets the timer. On slow connections with 8+ photos, the last photo(s) could theoretically arrive after the timer fires, causing them to be processed as a separate (incomplete) group. This is testTimings.mediaGroupFlushMs internally but is not exposed as a user-configurable option.
Expected Behavior
When one or more photos in a media group fail to download, the user should receive an error reply indicating which images could not be processed, e.g.:
"Received 7 of 8 images — 1 photo could not be fetched (download failed). Please resend the missing image."
Suggested Fix
In processMediaGroup, track failed photo count and send a follow-up error reply after processing:
let failedCount = 0;
for (const item of entry.messages) {
try {
media = await resolveMedia(...);
} catch (mediaErr) {
if (!isRecoverableMediaGroupError(mediaErr)) throw mediaErr;
runtime.log?.(warn(`media group: skipping photo...`));
failedCount++;
continue;
}
if (media) allMedia.push(...);
else failedCount++;
}
if (failedCount > 0) {
// send user-visible warning reply
await sendReply(primaryEntry.ctx, `⚠️ ${failedCount} of ${entry.messages.length} images could not be fetched and were skipped.`);
}
Summary
When sending multiple images as a Telegram media group (album), if one photo fails to download (network error, API timeout, file too large, etc.), it is silently dropped with no notification to the user. The AI receives fewer images than were sent, with no indication of what happened.
Version:
2026.3.23-2Channel: Telegram
Reproduction
Root Cause
1. Silent skip on download failure (
pi-embedded-CbCYZxIb.js,processMediaGroup)When
resolveMediathrows a recoverable error (MediaFetchError,MediaSizeLimitError) or returnsnull(aftergetFile()exhausts 3 retries), the photo is just skipped. No error reply is sent to the user.2. Partial download ("fragment") from idle timeout
downloadAndSaveTelegramFileuses a 30-second read idle timeout (TELEGRAM_DOWNLOAD_IDLE_TIMEOUT_MS = 30000). A large image that stalls mid-download can produce an incomplete file that gets passed to the AI as valid media.3. Timer race condition (minor)
The media group buffer uses a 500ms flush timer (
mediaGroupTimeoutMs = 500). Each incoming photo resets the timer. On slow connections with 8+ photos, the last photo(s) could theoretically arrive after the timer fires, causing them to be processed as a separate (incomplete) group. This istestTimings.mediaGroupFlushMsinternally but is not exposed as a user-configurable option.Expected Behavior
When one or more photos in a media group fail to download, the user should receive an error reply indicating which images could not be processed, e.g.:
Suggested Fix
In
processMediaGroup, track failed photo count and send a follow-up error reply after processing: