DIYgod/RSSHub · error · Error

Collection Not Found

Error message

Collection Not Found

What it means

Thrown by the Lofter collection handler (lib/routes/lofter/collection.ts:39) when the Lofter Android API response has no `response` field — i.e. the collection id does not exist, was deleted, or the API returned an error envelope. The check is `if (!response.data.response)`.

Source

Thrown at lib/routes/lofter/collection.ts:39

    maintainers: ['SrakhiuMeow'],
    handler,
};

async function fetchCollection(collectionID, limit, offset = 0) {
    const response = await got({
        method: 'post',
        url: 'https://api.lofter.com/v1.1/postCollection.api?product=lofter-android-7.6.12',
        body: new URLSearchParams({
            collectionid: collectionID,
            limit: limit.toString(),
            method: 'getCollectionDetail',
            offset: offset.toString(),
            order: '0',
        }),
    });

    if (!response.data.response) {
        throw new Error('Collection Not Found');
    }

    const data = response.data.response;

    return {
        title: data.collection.name || 'Lofter Collection',
        link: data.blogInfo.homePageUrl || 'https://www.lofter.com/',
        description: data.collection.description || 'No description provided.',
        items: data.items,
    };
}

async function handler(ctx) {
    const collectionID = ctx.req.param('collectionID');
    const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : '50';

    const response = await cache.tryGet(collectionID, () => fetchCollection(collectionID, Number(limit)), config.cache.routeExpire, false);

View on GitHub (pinned to bed535e087)

Solutions

  1. Verify the collection id by opening `https://www.lofter.com/front/blog/collection?collectionId=<id>` in a browser.
  2. Inspect the raw `response.data` to see whether the API returned an error code/message under a different key.
  3. If the envelope changed, update the guard and the downstream `data.collection`/`data.blogInfo` accesses.

Example fix

// before
if (!response.data.response) {
    throw new Error('Collection Not Found');
}

// after: surface the API error meta when present
if (!response.data.response) {
    const meta = response.data.meta || response.data;
    throw new Error(`Collection Not Found: ${JSON.stringify(meta).slice(0, 200)}`);
}
Defensive patterns

Strategy: validation

Validate before calling

function collectionExists(data: { response?: unknown }): boolean {
    return Boolean(data && data.response);
}
const data = (await got(...)).data;
if (!collectionExists(data)) throw new TypeError(`Lofter collection '${collectionID}' not found`);

Type guard

interface LofterCollectionResponse { response: { collection: { name: string }; blogInfo: { homePageUrl: string }; items: unknown[] } }
function isLofterCollectionResponse(d: unknown): d is LofterCollectionResponse {
    return typeof d === 'object' && d !== null && 'response' in d && !!((d as any).response);
}

Try / catch

try {
    return await fetchLofterCollection(collectionID);
} catch (e) {
    if (e instanceof Error && /Collection Not Found/.test(e.message)) {
        return { notFound: true, collectionID };
    }
    throw e;
}

Prevention

When it happens

Trigger: Requesting `/lofter/collection/<id>/...` with a non-existent or deleted collection id; the Lofter API changed its envelope and moved data elsewhere; rate limiting/error payload lacks the `response` key.

Common situations: Stale collection id from an old link; collection made private; Lofter API version bump (`postCollection.api` signature change).

Related errors


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