jackwener/OpenCLI · error · CommandExecutionError

xiaohongshu collection API returned malformed data

Error message

xiaohongshu collection API returned malformed data

What it means

extractNotesFromResponses expects each collection API payload to carry its data under payload.data as an object. When the unwrapped payload is an object but data is missing or not an object (e.g. {success:false} or {data:null}), it throws CommandExecutionError. The API contract is that note lists live inside data.notes or data.note_list.

Source

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

        title: toCleanString(noteCard.display_title ?? noteCard.displayTitle ?? noteCard.title ?? entry.title ?? entry.display_title),
        author: toCleanString(user.nickname ?? user.nick_name ?? user.name),
        likes: toCleanString(interact.liked_count ?? interact.likedCount ?? 0) || '0',
        type: toCleanString(noteCard.type ?? entry.type),
        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;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-login / refresh session cookies and retry
  2. Log the offending payload (JSON.stringify(payload)) to see the API error code
  3. Slow down request rate to avoid API-level errors
  4. Check for xiaohongshu API schema changes and update field mapping

Example fix

// before
const payload = JSON.parse(body); // payload = {code:-1, data:null}
rows = extractNotesFromResponses([payload], userId); // throws
// after
if (payload && payload.data) {
  rows = extractNotesFromResponses([payload], userId);
} else {
  console.error('API envelope:', JSON.stringify(payload));
}
Defensive patterns

Strategy: type-guard

Validate before calling

const hasDataObject = (payload) => payload && typeof payload === 'object' && payload.data && typeof payload.data === 'object' && !Array.isArray(payload.data);

Type guard

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

Try / catch

try { rows = extractNotesFromResponses(reqs, userId); } catch (e) { if (String(e.message).includes('malformed data')) { console.warn('API envelope:', JSON.stringify(reqs)); rows = []; } else throw e; }

Prevention

When it happens

Trigger: The xiaohongshu collection endpoint returns an error envelope like {code:..., msg:'...', data:null}, or the API response schema changed so notes no longer sit under data.

Common situations: Rate-limited or partially failed API calls returning error envelopes; xiaohongshu changing their internal API response shape; hitting the endpoint without proper cookies causing a soft error object.

Understand the failure class

Related errors


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