jackwener/OpenCLI · error · CommandExecutionError

xiaohongshu creator-note-detail: malformed capture for ${suf

Error message

xiaohongshu creator-note-detail: malformed capture for ${suffix}

What it means

parseCapturedJson validates a network capture record before parsing its body. The capture must be an object with ok === true and a string body; when the capture itself is null, a primitive, or otherwise not an object, this error reports 'malformed capture' for the endpoint suffix, meaning the interception layer never produced a usable record.

Source

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

    }
    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') {
        throw new CommandExecutionError(`xiaohongshu creator-note-detail: malformed capture for ${suffix}`);
    }
    if (capture.ok !== true) {
        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned HTTP ${capture.status ?? 'non-2xx'}`);
    }
    if (typeof capture.body !== 'string') {
        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned a non-text body`);
    }
    try {
        const envelope = JSON.parse(capture.body);
        const payload = isPlainObject(envelope) && Object.hasOwn(envelope, 'data') ? envelope.data : envelope;
        return validateCapturedPayload(payload, endpoint);
    }
    catch {
        throw new CommandExecutionError(`xiaohongshu creator-note-detail: signed API ${suffix} returned invalid JSON or payload shape`);
    }
}
// Capture the dashboard's signed datacenter/note responses on window.__xhsCapture
// since a direct fetch() from page.evaluate bypasses the x-s signing and gets 406.

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry — the request may simply not have been captured this run
  2. Ensure response listeners are attached before navigation and wait long enough for all signed endpoints to fire
  3. Log which endpoint suffix failed and inspect network traffic to confirm the request occurred
  4. Check whether risk control/login wall prevented the creator API calls entirely (see SECURITY_BLOCK/AuthRequiredError)

Example fix

// before
if (!capture || typeof capture !== 'object') {
    throw new CommandExecutionError(`... malformed capture for ${suffix}`);
}
// after
if (!capture || typeof capture !== 'object') {
    // one retry: reload and re-capture before failing
    capture = await captureNoteDetailPayload(page, endpoint, { retry: true });
    if (!capture || typeof capture !== 'object') {
        throw new CommandExecutionError(`... malformed capture for ${suffix}`);
    }
}
Defensive patterns

Strategy: retry

Type guard

const isCapture = (c) => c !== null && typeof c === 'object' && c.ok === true && typeof c.body === 'string';

Try / catch

try {
  const detail = await cli.creatorNoteDetail(noteId);
} catch (err) {
  if (err.message.includes('malformed capture for')) {
    await sleep(3000);
    return cli.creatorNoteDetail(noteId); // capture listeners may have missed the request
  }
  throw err;
}

Prevention

When it happens

Trigger: captureNoteDetailPayload's page capture returned null/undefined (the response never matched the listener or the wait timed out) or returned a non-object record; validateCapturedJson is then invoked with that bad capture.

Common situations: The signed API request never fired (page blocked, navigation too fast); response listener registered after the request completed; capture object shape changed in the driver layer; page.evaluate/page.wait wrapper returns null on timeout.

Understand the failure class

Related errors


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