jackwener/OpenCLI · error · CommandExecutionError
${webHost} feed: malformed feed item
Error message
${webHost} feed: malformed feed item What it means
Each entry in data.items must be a non-null object. runFeed throws 'malformed feed item' when a row is null, undefined, or a primitive. This is a per-item integrity check while building the result rows.
Source
Thrown at clis/xiaohongshu/feed.js:118
// Pinia store hydrates from SSR; give the page a beat to finish
// bootstrapping before reading the array.
await page.wait({ time: 2 });
const data = unwrapEvaluateResult(await page.evaluate(FEEDS_READ_JS));
if (!data || typeof data !== 'object') {
throw new CommandExecutionError(`${webHost} feed: unexpected evaluate response`);
}
if (data.error) {
throw new CommandExecutionError(`${webHost} feed: ${data.error}`, `The SPA may still be hydrating; reload ${webHost}/explore and retry.`);
}
if (!Array.isArray(data.items)) {
throw new CommandExecutionError(`${webHost} feed: unexpected items payload shape`);
}
const rows = [];
for (const row of data.items) {
if (rows.length >= limit)
break;
if (!row || typeof row !== 'object') {
throw new CommandExecutionError(`${webHost} feed: malformed feed item`);
}
const id = toCleanString(row.id);
if (!id) {
throw new CommandExecutionError(`${webHost} feed: feed item is missing note id`);
}
const xsecToken = toCleanString(row.xsecToken);
if (!xsecToken) {
throw new CommandExecutionError(`${webHost} feed: feed item ${id} is missing xsecToken; cannot build a signed drill-down URL`);
}
rows.push({
id,
title: toCleanString(row.title),
type: toCleanString(row.type),
author: toCleanString(row.author),
likes: toCleanString(row.likes),
url: buildFeedNoteUrl(webHost, id, xsecToken),
});
}View on GitHub (pinned to 49907e53dc)
Solutions
- Filter out non-object rows before parsing instead of failing the whole command
- Update FEEDS_READ_JS to normalize items to objects
- Retry after full hydration; placeholder rows often disappear once loaded
- Log data.items to identify which entries are malformed
Example fix
// before
for (const row of data.items) {
if (!row || typeof row !== 'object') {
throw new CommandExecutionError(`${webHost} feed: malformed feed item`);
}
// after
for (const row of data.items.filter(r => r && typeof r === 'object')) {
// skip malformed rows instead of aborting Defensive patterns
Strategy: type-guard
Validate before calling
const cleanItems = (data.items ?? []).filter(r => r && typeof r === 'object');
Type guard
function isFeedItem(row) { return !!row && typeof row === 'object' && !Array.isArray(row); } Try / catch
try {
const rows = await runFeed(page, webHost, limit);
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('malformed feed item')) {
// filter/skip bad rows or refresh the page and retry
} else throw err;
} Prevention
- Filter non-object rows client-side before mapping
- Skip placeholder/ad/skeleton entries
- Re-check item structure after site updates
When it happens
Trigger: data.items contains null/undefined entries or primitive values (strings/numbers) instead of note objects.
Common situations: Site inserts placeholder/ad entries as null, partial SSR hydration leaving holes in the items array, site schema change where items are keyed objects rather than an array of objects.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${webHost} feed: feed item is missing note id
- archive snapshots returned malformed CDX payload: snapshot r
- archive snapshots returned malformed CDX payload: snapshot r
- Ctrip flight API returned an itinerary without an id
- Ctrip flight API returned malformed itinerary at index ${ind
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b3fda962bae72219.
Report an issue: GitHub.