jackwener/OpenCLI · error · CommandExecutionError
Pixiv pages API returned malformed payload
Error message
Pixiv pages API returned malformed payload
What it means
Thrown when the pixiv /ajax/illust/{id}/pages endpoint returns a JSON body that is not an array. The library expects an array of page objects; anything else means the API contract changed or the response was an error/HTML page that was not caught as a not-found.
Source
Thrown at clis/pixiv/download.js:37
domain: 'www.pixiv.net',
strategy: Strategy.COOKIE,
args: [
{ name: 'illust-id', positional: true, required: true, help: 'Illustration ID' },
{ name: 'output', default: './pixiv-downloads', help: 'Output directory' },
],
columns: ['index', 'type', 'status', 'size'],
func: async (page, kwargs) => {
const illustId = String(kwargs['illust-id'] ?? '');
const output = String(kwargs.output ?? './pixiv-downloads');
if (!/^\d+$/.test(illustId)) {
throw new CommandExecutionError(`Invalid illustration ID: ${illustId}`);
}
// pixivFetch handles navigate + error checking; returns the response body directly
const pages = await pixivFetch(page, `/ajax/illust/${illustId}/pages`, {
notFoundMsg: `Illustration not found: ${illustId}`,
});
if (!Array.isArray(pages)) {
throw new CommandExecutionError('Pixiv pages API returned malformed payload');
}
if (pages.length === 0) {
throw new EmptyResultError('pixiv download', `No images found for illustration ${illustId}.`);
}
// Extract cookies for authenticated downloads
const cookies = formatCookieHeader(await page.getCookies({ domain: 'pixiv.net' }));
// Create output directory
const outputDir = path.join(output, illustId);
fs.mkdirSync(outputDir, { recursive: true });
const results = [];
for (let i = 0; i < pages.length; i++) {
const p = pages[i];
const url = p.urls?.original || p.urls?.regular || '';
if (!url) {
results.push({ index: i + 1, type: 'image', status: 'failed', size: 'No URL' });
continue;
}
try {View on GitHub (pinned to 49907e53dc)
Solutions
- Retry after a delay and reduce request rate to avoid pixiv throttling
- Re-authenticate / refresh pixiv cookies so the AJAX endpoint returns real data
- Log or inspect the raw response body to confirm what pixiv actually returned
- Check whether pixiv changed the /ajax/illust/{id}/pages response format and update the tool
Defensive patterns
Strategy: try-catch
Validate before calling
const body = await fetch(`https://www.pixiv.net/ajax/illust/${id}/pages`);
const ct = body.headers.get('content-type') || '';
if (!ct.includes('json')) throw new Error('Non-JSON response from pixiv'); Type guard
const isPagesArray = (v) => Array.isArray(v) && v.length >= 0;
Try / catch
try {
await pixivDownload({ illustId });
} catch (e) {
if (e.message === 'Pixiv pages API returned malformed payload') {
await sleep(5000); // back off, likely throttled
// retry once, then inspect raw response
} else throw e;
} Prevention
- Rate-limit pixiv requests to avoid bot detection
- Keep pixiv cookies fresh and export them after login
- Capture the raw response body for debugging when this fires
- Watch for pixiv AJAX API schema changes after tool failures spike
When it happens
Trigger: Pixiv returns an unexpected object or null for the pages endpoint (rate limiting page, login redirect, HTML error page parsed as JSON, or a pixiv API schema change).
Common situations: Aggressive scripted downloading triggers pixiv rate limiting or bot detection; user session is invalid so a redirect payload is returned; pixiv changes their internal AJAX API shape.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${label} returned an unexpected response
- ${label} returned HTTP ${resp.status}: ${summarizeApiError(p
- arXiv API HTTP ${resp.status}
- Bilibili view API returned a malformed payload during paid-c
- 获取视频分P信息失败: ${error?.message || error}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e0b5f0412896804f.
Report an issue: GitHub.