DIYgod/RSSHub · error · Error

Invalid API response: ${JSON.stringify(response)}

Error message

Invalid API response: ${JSON.stringify(response)}

What it means

Thrown by the bestblogs feeds route after POSTing to the bestblogs.dev resource/list API when the response does not match the expected shape { data: { dataList: [...] } }. The whole response is JSON-stringified into the message so the malformed payload is visible in the error.

Source

Thrown at lib/routes/bestblogs/feeds.ts:88

    const apiRequest = new APIRequest({
        category,
        pageSize: defaultPageSize,
        qualifiedFilter: category === 'featured' ? 'true' : 'false',
        timeFilter: defaultTimeFilter,
    });

    const apiUrl = 'https://api.bestblogs.dev/api/resource/list';
    const response = await ofetch(apiUrl, {
        headers: {
            'Content-Type': 'application/json',
        },
        method: 'POST',
        body: apiRequest.toJson(),
    });

    if (!response || !response.data || !response.data.dataList) {
        throw new Error('Invalid API response: ' + JSON.stringify(response));
    }

    const articles = response.data.dataList;

    const items = articles.map((article) => ({
        title: article.title,
        link: article.url,
        description: article.summary,
        pubDate: parseDate(article.publishDateTimeStr),
        author: Array.isArray(article.authors) ? article.authors.map((author) => ({ name: author })) : [{ name: article.authors }],
        category: article.category,
    }));

    return {
        title: 'Bestblogs.dev',
        link: 'https://www.bestblogs.dev/feeds',
        item: items,
    };

View on GitHub (pinned to bed535e087)

Solutions

  1. Retry shortly to rule out a transient outage; if it persists, inspect the JSON in the error message to see what the API actually returned.
  2. If the API schema changed, update the response.data.dataList access path (and the article field mappings) to match the new contract.
  3. Consider validating with a schema (e.g. zod) and throwing a narrower error that distinguishes 'empty' from 'wrong shape'.

Example fix

// before
if (!response || !response.data || !response.data.dataList) {
    throw new Error('Invalid API response: ' + JSON.stringify(response));
}

// after
const articles = response?.data?.dataList;
if (!Array.isArray(articles)) {
    throw new Error(`bestblogs API returned unexpected shape (code=${response?.code}, msg=${response?.message}). Raw: ${JSON.stringify(response).slice(0, 500)}`);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const articles = response?.data?.dataList;
if (!Array.isArray(articles)) {
    throw new Error(`bestblogs API unexpected shape: ${JSON.stringify(response).slice(0, 500)}`);
}

Type guard

function isBestblogsResponse(r: unknown): r is { data: { dataList: unknown[] } } {
    return !!r && typeof r === 'object' && Array.isArray((r as any)?.data?.dataList);
}

Try / catch

try {
    const response = await ofetch(apiUrl, { method: 'POST', body, headers });
    if (!isBestblogsResponse(response)) throw new Error('Invalid API response');
} catch (e) {
    // retry once for transient upstream errors, then propagate
    throw e;
}

Prevention

When it happens

Trigger: The bestblogs API returns an error envelope, an empty body, a shape change (e.g. dataList renamed), a non-JSON page, or a CDN/edge error (HTML 502 page parsed into an object).

Common situations: Bestblogs ships a new API version with a different response schema; rate-limiting returns an error object; temporary outage returns HTML that ofetch parsed to null.

Related errors


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