jackwener/OpenCLI · error · CommandExecutionError

xiaohongshu creator-note-detail: signed API ${suffix} return

Error message

xiaohongshu creator-note-detail: signed API ${suffix} returned a malformed payload

What it means

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.

Source

Thrown at clis/xiaohongshu/creator-note-detail.js:284

    return Object.keys(captureMap).find((url) => detailApiEndpointForUrl(url)?.suffix === suffix);
}
function isPlainObject(value) {
    return value !== null && typeof value === 'object' && !Array.isArray(value);
}
function assertOptionalArray(payload, key, suffix) {
    if (key in payload && !Array.isArray(payload[key])) {
        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned malformed ${key}`);
    }
}
function assertOptionalPlainObject(payload, key, suffix) {
    if (key in payload && !isPlainObject(payload[key])) {
        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned malformed ${key}`);
    }
}
function validateCapturedPayload(payload, endpoint) {
    const suffix = endpoint.suffix;
    if (!isPlainObject(payload)) {
        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned a malformed payload`);
    }
    if (endpoint.key === 'noteBase') {
        assertOptionalPlainObject(payload, 'hour', suffix);
        assertOptionalPlainObject(payload, 'day', suffix);
    }
    if (endpoint.key === 'audienceSource') {
        assertOptionalArray(payload, 'source', suffix);
    }
    if (endpoint.key === 'audienceSourceDetail') {
        for (const key of ['gender', 'age', 'city', 'interest']) {
            assertOptionalArray(payload, key, suffix);
        }
    }
    return payload;
}
function parseCapturedJson(capture, endpoint) {
    const suffix = endpoint.suffix;
    if (!capture || typeof capture !== 'object') {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the raw capture.body to see exactly what JSON the endpoint returned
  2. Confirm the request hit the real signed API and not a gateway/error endpoint returning scalar JSON
  3. Relax or branch validateCapturedPayload to handle top-level arrays if the API legitimately changed shape
  4. Retry — degraded/gateway responses are often transient

Example fix

// before
if (!isPlainObject(payload)) {
    throw new CommandExecutionError(`... returned a malformed payload`);
}
// after
if (!isPlainObject(payload)) {
    if (Array.isArray(payload)) {
        payload = { items: payload }; // wrap top-level array
    } else {
        throw new CommandExecutionError(`... returned a malformed payload`);
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

let parsed; try { parsed = JSON.parse(body); } catch { return false; }
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) return false;

Type guard

const isPlainObject = v => v !== null && typeof v === 'object' && !Array.isArray(v);

Try / catch

try {
  const detail = await cli.creatorNoteDetail(noteId);
} catch (err) {
  if (err.message.includes('returned a malformed payload')) {
    // retry — gateway/scalar JSON bodies are often transient
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/153de90a8b51887c. Report an issue: GitHub.