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

  1. Inspect row keys in DevTools to find where the note id now lives
  2. Update FEEDS_READ_JS or row mapping to read the renamed field (e.g. row.noteId)
  3. Skip items without ids instead of aborting the whole feed
  4. 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

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


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