{"record":{"id":"153de90a8b51887c","repo":"jackwener/OpenCLI","slug":"xiaohongshu-creator-note-detail-signed-api-suff-153de9","errorCode":null,"errorMessage":"xiaohongshu creator-note-detail: signed API ${suffix} returned a malformed payload","messagePattern":"xiaohongshu creator-note-detail: signed API (.+?) returned a malformed payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/creator-note-detail.js","lineNumber":284,"sourceCode":"    return Object.keys(captureMap).find((url) => detailApiEndpointForUrl(url)?.suffix === suffix);\n}\nfunction isPlainObject(value) {\n    return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\nfunction assertOptionalArray(payload, key, suffix) {\n    if (key in payload && !Array.isArray(payload[key])) {\n        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned malformed ${key}`);\n    }\n}\nfunction assertOptionalPlainObject(payload, key, suffix) {\n    if (key in payload && !isPlainObject(payload[key])) {\n        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned malformed ${key}`);\n    }\n}\nfunction validateCapturedPayload(payload, endpoint) {\n    const suffix = endpoint.suffix;\n    if (!isPlainObject(payload)) {\n        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned a malformed payload`);\n    }\n    if (endpoint.key === 'noteBase') {\n        assertOptionalPlainObject(payload, 'hour', suffix);\n        assertOptionalPlainObject(payload, 'day', suffix);\n    }\n    if (endpoint.key === 'audienceSource') {\n        assertOptionalArray(payload, 'source', suffix);\n    }\n    if (endpoint.key === 'audienceSourceDetail') {\n        for (const key of ['gender', 'age', 'city', 'interest']) {\n            assertOptionalArray(payload, key, suffix);\n        }\n    }\n    return payload;\n}\nfunction parseCapturedJson(capture, endpoint) {\n    const suffix = endpoint.suffix;\n    if (!capture || typeof capture !== 'object') {","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/creator-note-detail.js#L266-L302","documentation":"validateCapturedPayload first requires the parsed signed-API response itself to be a plain object. When the JSON body parses to something else (array, string, number, null), the whole payload is declared malformed for the endpoint suffix.","triggerScenarios":"parseCapturedJson receives capture.ok === true with a string body, JSON.parse succeeds but yields a non-object (e.g. body is 'null', '\"ok\"', '[...]'), then validateCapturedPayload throws before per-key checks.","commonSituations":"API returned a bare null/true/false/number body (proxy or gateway JSON); a WAF/challenge page stripped to a non-object JSON; API version change returning a top-level array of errors.","solutions":["Log the raw capture.body to see exactly what JSON the endpoint returned","Confirm the request hit the real signed API and not a gateway/error endpoint returning scalar JSON","Relax or branch validateCapturedPayload to handle top-level arrays if the API legitimately changed shape","Retry — degraded/gateway responses are often transient"],"exampleFix":"// before\nif (!isPlainObject(payload)) {\n    throw new CommandExecutionError(`... returned a malformed payload`);\n}\n// after\nif (!isPlainObject(payload)) {\n    if (Array.isArray(payload)) {\n        payload = { items: payload }; // wrap top-level array\n    } else {\n        throw new CommandExecutionError(`... returned a malformed payload`);\n    }\n}","handlingStrategy":"type-guard","validationCode":"let parsed; try { parsed = JSON.parse(body); } catch { return false; }\nif (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) return false;","typeGuard":"const isPlainObject = v => v !== null && typeof v === 'object' && !Array.isArray(v);","tryCatchPattern":"try {\n  const detail = await cli.creatorNoteDetail(noteId);\n} catch (err) {\n  if (err.message.includes('returned a malformed payload')) {\n    // retry — gateway/scalar JSON bodies are often transient\n  } else throw err;\n}","preventionTips":["Confirm requests hit the signed API, not a gateway/WAF JSON response","Log raw bodies on failure for quick diagnosis","Retry transient degraded responses","Version-check the creator API surface periodically"],"tags":["validation","api-response","json","signed-api"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}