{"record":{"id":"dffcb734d31cd2b4","repo":"jackwener/OpenCLI","slug":"xiaohongshu-creator-note-detail-signed-api-suff-dffcb7","errorCode":null,"errorMessage":"xiaohongshu creator-note-detail: signed API ${suffix} returned invalid JSON or payload shape","messagePattern":"xiaohongshu creator-note-detail: signed API (.+?) returned invalid JSON or payload shape","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/creator-note-detail.js","lineNumber":317,"sourceCode":"}\nfunction parseCapturedJson(capture, endpoint) {\n    const suffix = endpoint.suffix;\n    if (!capture || typeof capture !== 'object') {\n        throw new CommandExecutionError(`xiaohongshu creator-note-detail: malformed capture for ${suffix}`);\n    }\n    if (capture.ok !== true) {\n        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned HTTP ${capture.status ?? 'non-2xx'}`);\n    }\n    if (typeof capture.body !== 'string') {\n        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned a non-text body`);\n    }\n    try {\n        const envelope = JSON.parse(capture.body);\n        const payload = isPlainObject(envelope) && Object.hasOwn(envelope, 'data') ? envelope.data : envelope;\n        return validateCapturedPayload(payload, endpoint);\n    }\n    catch {\n        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned invalid JSON or payload shape`);\n    }\n}\n// Capture the dashboard's signed datacenter/note responses on window.__xhsCapture\n// since a direct fetch() from page.evaluate bypasses the x-s signing and gets 406.\nasync function installXhsFetchCaptureHook(page) {\n    await page.evaluate(`(() => {\n    const targetPaths = ${JSON.stringify(DETAIL_API_ENDPOINTS.map((endpoint) => endpoint.suffix))};\n    const shouldCapture = (url) => {\n      try {\n        return targetPaths.includes(new URL(String(url), window.location.origin).pathname);\n      } catch (_) {\n        return false;\n      }\n    };\n    // Reset the buffer every call so stale captures from a previous run on\n    // the same tab cannot leak into the current navigation's harvest.\n    window.__xhsCapture = {};\n    if (window.__xhsCaptureInstalled) return;","sourceCodeStart":299,"sourceCodeEnd":335,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/creator-note-detail.js#L299-L335","documentation":"parseCapturedJson throws this CommandExecutionError when the captured response body cannot be JSON.parsed, or the extracted payload fails validateCapturedPayload. It collapses JSON syntax errors and payload-shape validation failures into one message, so the signed endpoint replied 2xx with text that is not the expected JSON envelope/data shape.","triggerScenarios":"The datacenter/note endpoint returns HTML (login redirect page), an empty body, an anti-bot challenge page, or JSON whose shape (envelope.data / expected fields) doesn't match what validateCapturedPayload requires for that endpoint.","commonSituations":"Session expired mid-run so a 2xx redirect/HTML page was captured; Xiaohongshu changed the API response schema after a dashboard update; risk control served a verification/JSONP/error page; note has no statistics yet so the payload shape differs.","solutions":["Re-login to creator.xiaohongshu.com and retry — an HTML login page captured in place of JSON is the most common cause.","Inspect the raw body (network tab) for the failing endpoint to see whether it is HTML, empty, or changed JSON.","Retry later if risk control is serving challenge pages; reduce request frequency between runs.","Update the CLI / report a schema change if Xiaohongshu altered the datacenter/note response envelope.","Confirm the note actually has detail statistics; a brand-new or deleted note can produce an unexpected shape."],"exampleFix":"// before\nconst rows = await run('xiaohongshu creator-note-detail', { 'note-id': id });\n// after\ntry {\n  const rows = await run('xiaohongshu creator-note-detail', { 'note-id': id });\n} catch (e) {\n  if (/invalid JSON or payload shape/.test(e.message)) {\n    await ensureCreatorLogin(page); // re-open creator.xiaohongshu.com, confirm dashboard loads\n    return await run('xiaohongshu creator-note-detail', { 'note-id': id });\n  }\n  throw e;\n}","handlingStrategy":"validation","validationCode":"// pre-check: dashboard session returns JSON\nconst probe = await fetch('https://creator.xiaohongshu.com/new/home', { headers: { accept: 'text/html' } });\nif (!probe.ok || (await probe.text()).includes('login')) await relogin();","typeGuard":"function looksLikeEnvelope(x) {\n  return typeof x === 'object' && x !== null && !Array.isArray(x);\n}","tryCatchPattern":"try {\n  return await run('xiaohongshu creator-note-detail', { 'note-id': id });\n} catch (e) {\n  if (/invalid JSON or payload shape/.test(e.message)) {\n    await ensureCreatorLogin();\n    return await run('xiaohongshu creator-note-detail', { 'note-id': id });\n  }\n  throw e;\n}","preventionTips":["Verify login before each run; HTML login pages captured as 2xx are the top cause.","Keep the CLI updated for Xiaohongshu schema changes.","Avoid running during risk-control-prone bursts; add delays between commands.","Check the network tab once if it persists, to see whether the body is HTML, empty, or new-schema JSON.","Test with notes that already have statistics data."],"tags":["json","schema-validation","xiaohongshu","session-expired"],"backgroundTag":"invalid-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}