DIYgod/RSSHub · warning · Error

no thumbnails available

Error message

no thumbnails available

What it means

streamThumbnail throws when a Telegram Api.Document has no thumbnails (doc.thumbs is undefined or an empty array). With no thumb to select, there is nothing to stream as a preview image for that document.

Source

Thrown at lib/routes/telegram/channel-media.ts:83

    return 0;
}

function chooseLargestThumb(thumbs: Api.TypePhotoSize[]) {
    thumbs = [...thumbs].toSorted((a, b) => sortThumb(a) - sortThumb(b));
    return thumbs.pop();
}

export async function* streamThumbnail(client: TelegramClient, doc: Api.Document) {
    if ((doc.thumbs?.length ?? 0) > 0) {
        const size = chooseLargestThumb(doc.thumbs!);
        if (size instanceof Api.PhotoCachedSize || size instanceof Api.PhotoStrippedSize) {
            yield ExpandInlineBytes(size.bytes);
        } else {
            yield* streamDocument(client, doc, size && 'type' in size ? size.type : '');
        }
        return;
    }
    throw new Error('no thumbnails available');
}

export async function* streamDocument(client: TelegramClient, obj: Api.Document, thumbSize = '', offset?: bigInt.BigInteger, limit?: bigInt.BigInteger) {
    const requestSize = 512 * 1024; // MAX_CHUNK_SIZE
    let skip = offset ? offset.mod(requestSize).toJSNumber() : 0;
    const alignedOffset = offset?.subtract(skip);
    // console.log('starting iterDownload');
    const chunks = client.iterDownload(
        new Api.InputDocumentFileLocation({
            id: obj.id,
            accessHash: obj.accessHash,
            fileReference: obj.fileReference,
            thumbSize,
        }),
        {
            requestSize,
            dcId: obj.dcId,
            offset: alignedOffset,

View on GitHub (pinned to bed535e087)

Solutions

  1. Fall back to streamDocument(client, doc) for the full media when there is no thumbnail, instead of throwing.
  2. At the call site, check doc.thumbs?.length before choosing streamThumbnail vs streamDocument so non-previewable media is handled gracefully.
  3. Return a 404/empty-thumbnail response to the client rather than crashing the route handler.

Example fix

// before
if ((doc.thumbs?.length ?? 0) > 0) {
    ... return;
}
throw new Error('no thumbnails available');

// after: fall back to the full document stream
if ((doc.thumbs?.length ?? 0) > 0) {
    ...
    return;
}
// no thumbnail; serve the original file instead of erroring
yield* streamDocument(client, doc);
Defensive patterns

Strategy: validation

Validate before calling

function hasThumbnail(doc: Api.Document): boolean {
    return Array.isArray(doc.thumbs) && doc.thumbs.length > 0;
}
// if (!hasThumbnail(doc)) { serve the full document instead of a thumbnail }

Type guard

function docHasThumbs(doc: Api.Document): doc is Api.Document & { thumbs: Api.TypePhotoSize[] } {
    return Array.isArray(doc.thumbs) && doc.thumbs.length > 0;
}

Try / catch

try {
    yield* streamThumbnail(client, doc);
} catch (e) {
    if (e instanceof Error && /no thumbnails available/.test(e.message)) {
        yield* streamDocument(client, doc); // full media fallback
        return;
    }
    throw e;
}

Prevention

When it happens

Trigger: A media request resolves to a document that legitimately carries no thumbnail (e.g. an audio file, a document without a preview, or a file whose thumbs were stripped). chooseLargestThumb is never reached because the length check short-circuits.

Common situations: Channel post points at an audio/sticker/file document without a thumbnail; the requested media type was a video whose thumbnail failed to populate; calling streamThumbnail instead of streamDocument for a non-image media.

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/7e655f478afea8a8. Report an issue: GitHub.