jackwener/OpenCLI · error · CommandExecutionError

xiaohongshu collection API returned malformed notes

Error message

xiaohongshu collection API returned malformed notes

What it means

After locating the data object, extractNotesFromResponses requires the notes array at data.notes or data.note_list. If neither key holds an array, it throws CommandExecutionError. This catches both missing keys and xiaohongshu switching the note-list field name.

Source

Thrown at clis/xiaohongshu/collection-helpers.js:99

        url,
    };
}

export function extractNotesFromResponses(requests, fallbackUserId) {
    const rows = [];
    const seen = new Set();
    for (const req of requests ?? []) {
        const payload = unwrapBrowserResult(req);
        if (!isObject(payload)) {
            throw new CommandExecutionError('xiaohongshu collection API returned a malformed payload');
        }
        const data = payload.data;
        if (!isObject(data)) {
            throw new CommandExecutionError('xiaohongshu collection API returned malformed data');
        }
        const notes = data.notes ?? data.note_list;
        if (!Array.isArray(notes))
            throw new CommandExecutionError('xiaohongshu collection API returned malformed notes');
        for (const entry of notes) {
            const row = mapCollectionNote(entry, { fallbackUserId });
            if (!row?.id || !row.url.includes('xsec_token=')) {
                throw new CommandExecutionError('xiaohongshu collection API returned a note without stable id/xsec token');
            }
            if (seen.has(row.id))
                continue;
            seen.add(row.id);
            rows.push(row);
        }
    }
    return rows;
}

export const EXTRACT_COLLECTION_DOM_JS = `
  (() => {
    const normalizeUrl = (href) => {
      if (!href) return '';

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Confirm the account/collection actually returns notes by checking the endpoint in a browser devtools session
  2. Capture and log Object.keys(payload.data) to find the new field name
  3. Update mapping to support the new key in a local fork or newer library version
  4. Retry later if the payload was transiently incomplete

Example fix

// before
const notes = data.notes ?? data.note_list;
// after (defensive, before calling extractNotesFromResponses)
const data = payload?.data ?? {};
const notes = data.notes ?? data.note_list ?? (data.items?.notes);
if (!Array.isArray(notes)) throw new Error('unexpected keys: ' + Object.keys(data));
Defensive patterns

Strategy: type-guard

Validate before calling

const notesOf = (payload) => payload?.data ? (payload.data.notes ?? payload.data.note_list) : undefined;
const hasNotesArray = (p) => Array.isArray(notesOf(p));

Type guard

const hasNotesArray = (p) => Array.isArray(p?.data?.notes ?? p?.data?.note_list);

Try / catch

try { rows = extractNotesFromResponses(reqs, userId); } catch (e) { if (String(e.message).includes('malformed notes')) { console.warn('data keys:', Object.keys(reqs[0]?.data ?? {})); rows = []; } else throw e; }

Prevention

When it happens

Trigger: data exists but has neither notes nor note_list arrays — e.g. an empty envelope {data:{}}, or the API renamed the field; also a scalar/null at those keys.

Common situations: First page fetched before any notes load; user with zero notes returning an empty object instead of an empty array; upstream API version change (notes vs note_list) not covered by either key.

Understand the failure class

Related errors


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