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
- 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.
- If the API schema changed, update the response.data.dataList access path (and the article field mappings) to match the new contract.
- 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
- Validate upstream JSON with a schema (zod) so shape changes fail loudly with context.
- Truncate the JSON in error messages to avoid log bloat.
- Distinguish 'empty result' from 'wrong shape' for clearer diagnostics.
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
- Unknown type: ${item.type}
- API error: ${response.message}
- API error: ${response.message}
- Douban 返回数据结构异常,可能触发反爬或限频。${details ? `上游信息:${details}` : ''
- ${detail.message}
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/4674709970c60d31.
Report an issue: GitHub.