{"record":{"id":"6b30b9901315c0b4","repo":"jackwener/OpenCLI","slug":"pixiv-novel-id-returned-malformed-detail-payloa-6b30b9","errorCode":null,"errorMessage":"Pixiv novel ${id} returned malformed detail payload","messagePattern":"Pixiv novel (.+?) returned malformed detail payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pixiv/novel.js","lineNumber":16,"sourceCode":"import { cli, Strategy } from '@jackwener/opencli/registry';\nimport { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';\nimport { pixivFetch } from './utils.js';\nimport { dateOnly, tagsToString } from './bookmark-utils.js';\n\nfunction optionalCount(value, label) {\n  if (value == null || value === '') return '';\n  if (!Number.isSafeInteger(value) || value < 0) {\n    throw new CommandExecutionError(`Pixiv novel returned malformed ${label}`);\n  }\n  return value;\n}\n\nfunction requireNovelBody(body, id) {\n  if (!body || Array.isArray(body) || typeof body !== 'object') {\n    throw new CommandExecutionError(`Pixiv novel ${id} returned malformed detail payload`);\n  }\n  const novelId = String(body.id ?? '').trim();\n  const title = String(body.title ?? '').trim();\n  const userName = String(body.userName ?? '').trim();\n  const userId = String(body.userId ?? '').trim();\n  if (!/^\\d+$/.test(novelId) || novelId !== id || !title || !userName || !/^\\d+$/.test(userId)) {\n    throw new CommandExecutionError(`Pixiv novel ${id} returned malformed detail payload`);\n  }\n  return { payload: body, identity: { novelId, title, userName, userId } };\n}\n\nexport function novelRowFromBody(body, id) {\n  const normalized = requireNovelBody(body, id);\n  const b = normalized.payload;\n  const identity = normalized.identity;\n  if (b.seriesNavData != null && (Array.isArray(b.seriesNavData) || typeof b.seriesNavData !== 'object')) {\n    throw new CommandExecutionError('Pixiv novel returned malformed series metadata');\n  }","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pixiv/novel.js#L1-L34","documentation":"requireNovelBody performs a structural pre-check on the Pixiv novel detail payload: body must be a non-null, non-array object. If it is null, an array, or a primitive, the library cannot extract the novel identity and throws CommandExecutionError naming the requested novel ID. This catches pages that failed to load or API calls that returned an unexpected top-level type.","triggerScenarios":"fetchNovelForDownload / novel detail fetch via pixivFetch returns null, an array, or a non-object (e.g. a parsed HTML string or error document) for the given novel id.","commonSituations":"Novel deleted or ID wrong so Pixiv returns a not-found/error page; not logged in / age-restricted or R-18 content blocked so the scraper receives a login page; rate-limiting returning an error body; network proxy mangling the response.","solutions":["Verify the novel ID exists by opening it on pixiv.net; retry with a valid, non-deleted novel ID.","Ensure you are authenticated (valid Pixiv session/cookies) — unauthenticated scrapes often return login pages instead of JSON.","Retry later if rate-limited (Pixiv throttling commonly returns non-data responses).","Update the library in case Pixiv changed its page structure and the scraper needs a fix."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"function looksLikeNovelBody(v) {\n  return v !== null && !Array.isArray(v) && typeof v === 'object';\n}\nif (!looksLikeNovelBody(body)) throw new Error('fetch failed — got non-object payload (login/error page?)');","typeGuard":"function isNovelDetailBody(v) {\n  return (\n    v !== null &&\n    !Array.isArray(v) &&\n    typeof v === 'object' &&\n    /^\\d+$/.test(String(v.id ?? '')) &&\n    typeof v.title === 'string' && v.title.length > 0 &&\n    /^\\d+$/.test(String(v.userId ?? ''))\n  );\n}","tryCatchPattern":"try {\n  const detail = await cli.pixiv.novelView({ id });\n} catch (e) {\n  if (/malformed detail payload/.test(e.message)) {\n    console.error(`Novel ${id} payload invalid — check the ID exists, you are logged in, and the novel is public.`);\n  } else throw e;\n}","preventionTips":["Verify the novel ID resolves on pixiv.net before scripting against it.","Maintain valid Pixiv cookies/login; R-18 or login-walled content returns error pages.","Back off and retry on rate limits before concluding the payload is malformed."],"tags":["pixiv","scraping","malformed-response","not-found"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}