jackwener/OpenCLI · error · CommandExecutionError
${webHost} feed: feed item is missing note id
Error message
${webHost} feed: feed item is missing note id What it means
Every feed item must carry a note id; runFeed throws 'feed item is missing note id' when toCleanString(row.id) is empty. Without the id, drill-down URLs cannot be built, so the item is rejected.
Source
Thrown at clis/xiaohongshu/feed.js:122
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),
});
}
if (rows.length === 0) {
throw new EmptyResultError(`${webHost}/feed`, 'No feed items in the hydrated store.');
}
return rows;View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect row keys in DevTools to find where the note id now lives
- Update FEEDS_READ_JS or row mapping to read the renamed field (e.g. row.noteId)
- Skip items without ids instead of aborting the whole feed
- Retry after hydration so skeleton items resolve to real ids
Example fix
// before const id = toCleanString(row.id); // after (tolerate renames) const id = toCleanString(row.id ?? row.noteId ?? row.idStr);
Defensive patterns
Strategy: validation
Validate before calling
const items = (data.items ?? []).filter(r => r && toCleanString(r.id ?? r.noteId ?? r.idStr));
Type guard
function hasNoteId(row) { return !!row && typeof row === 'object' && Boolean(toCleanString(row.id ?? row.noteId ?? row.idStr)); } Try / catch
try {
const rows = await runFeed(page, webHost, limit);
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('missing note id')) {
// skip the item or reload and retry once hydrated
} else throw err;
} Prevention
- Map all plausible id field names (id/noteId/idStr) in the row parser
- Wait for hydration so skeleton items resolve to real ids
- Filter id-less ad/placeholder cards before parsing
When it happens
Trigger: A row in data.items lacks an id field or has an id that trims to empty string (e.g. empty object, id renamed to noteId/idStr by a site change).
Common situations: Site schema rename (id -> noteId), ad/promoted cards without ids in the feed, skeleton items rendered before data binding.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- ${webHost} feed: malformed feed item
- 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/9b88dc670231e27a.
Report an issue: GitHub.