{"record":{"id":"ba991a55fd5604a7","repo":"jackwener/OpenCLI","slug":"pixiv-bookmark-item-returned-malformed-label","errorCode":null,"errorMessage":"Pixiv bookmark item returned malformed ${label}","messagePattern":"Pixiv bookmark item returned malformed (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pixiv/bookmark-utils.js","lineNumber":46,"sourceCode":"export function tagsToString(tags) {\n  if (tags == null) return '';\n  const values = Array.isArray(tags) ? tags : (Array.isArray(tags?.tags) ? tags.tags : null);\n  if (!values) {\n    throw new CommandExecutionError('Pixiv item returned malformed tags payload');\n  }\n  return values.map((entry) => {\n    const value = typeof entry === 'string' ? entry : entry?.tag;\n    if (typeof value !== 'string' || !value.trim()) {\n      throw new CommandExecutionError('Pixiv item returned malformed tag');\n    }\n    return value.trim();\n  }).join(', ');\n}\n\nfunction optionalCount(value, label, fallback = '') {\n  if (value == null || value === '') return fallback;\n  if (!Number.isSafeInteger(value) || value < 0) {\n    throw new CommandExecutionError(`Pixiv bookmark item returned malformed ${label}`);\n  }\n  return value;\n}\n\nexport function normalizeBookmarkWorks(body) {\n  if (Array.isArray(body)) return body;\n  if (Array.isArray(body?.works)) return body.works;\n  if (body?.works && typeof body.works === 'object') return Object.values(body.works);\n  throw new CommandExecutionError('Pixiv bookmarks returned malformed payload');\n}\n\nexport function bookmarkRow(work, index, type, bookmarkOwnerId) {\n  const item = requirePixivPayloadObject(work, 'Pixiv bookmark item');\n  const isNovel = type === 'novel';\n  const id = requirePixivId(item.id ?? (isNovel ? item.novelId : item.illustId), 'Pixiv bookmark item');\n  const title = requirePixivString(item.title ?? item.illustTitle, 'Pixiv bookmark item');\n  const author = requirePixivString(item.userName ?? item.user_name, 'Pixiv bookmark item');\n  const userId = requirePixivId(item.userId ?? item.user_id, 'Pixiv bookmark item');","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pixiv/bookmark-utils.js#L28-L64","documentation":"optionalCount validates optional numeric count fields (e.g. view/bookmark counts) on a Pixiv bookmark item. If a value is present but is not a non-negative safe integer, CommandExecutionError 'Pixiv bookmark item returned malformed <label>' is thrown with the field label.","triggerScenarios":"A bookmark item carrying a count as a formatted string ('1.2k'), a float, a negative number, or a number exceeding Number.MAX_SAFE_INTEGER from a non-standard endpoint.","commonSituations":"Proxy/mirror APIs that pre-format counts, scraped data instead of the official JSON, API changes making counts strings, mocks with placeholder values like 'N/A'.","solutions":["Ensure the count field is a plain non-negative integer in the item JSON","If using a proxy or scraper, convert counts to integers before passing the item to the row builders","Check for API/lib version drift and update, or pre-parse string counts with parseInt"],"exampleFix":"// before\nitem.totalView = '1.2k'\n// after\nitem.totalView = 1200","handlingStrategy":"validation","validationCode":"function hasValidCounts(item) { return ['totalView','totalBookmarks'].every(k => item?.[k] == null || item[k] === '' || (Number.isSafeInteger(item[k]) && item[k] >= 0)); }\nif (!hasValidCounts(item)) throw new Error('Bookmark item has malformed count fields');","typeGuard":"function isOptionalCount(v) { return v == null || v === '' || (Number.isSafeInteger(v) && v >= 0); }","tryCatchPattern":"try { const row = bookmarkRow(item); /* ... */ } catch (err) { if (err.message.startsWith('Pixiv bookmark item returned malformed')) { console.warn('Skipping item with malformed count:', item.id); return null; } throw err; }","preventionTips":["Pass raw numeric counts from the API; do not pre-format ('1.2k')","Coerce string counts to integers upstream when ingesting from scrapers/proxies","Validate numeric fields in the response schema before row building"],"tags":["pixiv","data-parsing","numeric-validation","api-response"],"backgroundTag":"malformed-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}