{"record":{"id":"e0b5f0412896804f","repo":"jackwener/OpenCLI","slug":"pixiv-pages-api-returned-malformed-payload-e0b5f0","errorCode":null,"errorMessage":"Pixiv pages API returned malformed payload","messagePattern":"Pixiv pages API returned malformed payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pixiv/download.js","lineNumber":37,"sourceCode":"    domain: 'www.pixiv.net',\n    strategy: Strategy.COOKIE,\n    args: [\n        { name: 'illust-id', positional: true, required: true, help: 'Illustration ID' },\n        { name: 'output', default: './pixiv-downloads', help: 'Output directory' },\n    ],\n    columns: ['index', 'type', 'status', 'size'],\n    func: async (page, kwargs) => {\n        const illustId = String(kwargs['illust-id'] ?? '');\n        const output = String(kwargs.output ?? './pixiv-downloads');\n        if (!/^\\d+$/.test(illustId)) {\n            throw new CommandExecutionError(`Invalid illustration ID: ${illustId}`);\n        }\n        // pixivFetch handles navigate + error checking; returns the response body directly\n        const pages = await pixivFetch(page, `/ajax/illust/${illustId}/pages`, {\n            notFoundMsg: `Illustration not found: ${illustId}`,\n        });\n        if (!Array.isArray(pages)) {\n            throw new CommandExecutionError('Pixiv pages API returned malformed payload');\n        }\n        if (pages.length === 0) {\n            throw new EmptyResultError('pixiv download', `No images found for illustration ${illustId}.`);\n        }\n        // Extract cookies for authenticated downloads\n        const cookies = formatCookieHeader(await page.getCookies({ domain: 'pixiv.net' }));\n        // Create output directory\n        const outputDir = path.join(output, illustId);\n        fs.mkdirSync(outputDir, { recursive: true });\n        const results = [];\n        for (let i = 0; i < pages.length; i++) {\n            const p = pages[i];\n            const url = p.urls?.original || p.urls?.regular || '';\n            if (!url) {\n                results.push({ index: i + 1, type: 'image', status: 'failed', size: 'No URL' });\n                continue;\n            }\n            try {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pixiv/download.js#L19-L55","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const body = await fetch(`https://www.pixiv.net/ajax/illust/${id}/pages`);\nconst ct = body.headers.get('content-type') || '';\nif (!ct.includes('json')) throw new Error('Non-JSON response from pixiv');","typeGuard":"const isPagesArray = (v) => Array.isArray(v) && v.length >= 0;","tryCatchPattern":"try {\n  await pixivDownload({ illustId });\n} catch (e) {\n  if (e.message === 'Pixiv pages API returned malformed payload') {\n    await sleep(5000); // back off, likely throttled\n    // retry once, then inspect raw response\n  } else throw e;\n}","preventionTips":["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"],"tags":["network","api","malformed-response"],"backgroundTag":"malformed-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}