jackwener/OpenCLI · error · CommandExecutionError

${webHost} feed: ${data.error}

Error message

${webHost} feed: ${data.error}

What it means

When the in-page feed script returns an object carrying an error field, runFeed surfaces it as CommandExecutionError '<webHost> feed: <error>' with the hint that the SPA may still be hydrating. This is the site-side error propagated to the CLI.

Source

Thrown at clis/xiaohongshu/feed.js:108

    return url.toString();
}

/**
 * Shared func-mode implementation. Exported so the rednote adapter can run the
 * same store read against www.rednote.com without duplicating the logic.
 */
export async function runFeed(page, kwargs, webHost) {
    const limit = parseLimit(kwargs.limit);
    await page.goto(`https://${webHost}/explore`);
    // 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`);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry after reloading https://<webHost>/explore and waiting for full render
  2. Log in again if the session expired
  3. Increase wait time or wait for a feed DOM selector before evaluating
  4. Retry later if the site is rate limiting or showing anti-bot challenges
  5. Update FEEDS_READ_JS if the store API changed

Example fix

// before
await page.wait({ time: 2 });
const data = unwrapEvaluateResult(await page.evaluate(FEEDS_READ_JS));
// after
await page.goto(`https://${webHost}/explore`, { waitUntil: 'networkidle' });
await page.waitForSelector('.note-item');
const data = unwrapEvaluateResult(await page.evaluate(FEEDS_READ_JS));
Defensive patterns

Strategy: retry

Validate before calling

await page.goto(`https://${webHost}/explore`, { waitUntil: 'networkidle' });
await page.waitForSelector('.note-item');

Type guard

function isHydratedFeed(d) { return !!d && typeof d === 'object' && !d.error; }

Try / catch

try {
  await runFeed(page, webHost, limit);
} catch (err) {
  if (err instanceof CommandExecutionError && /feed: /.test(err.message) && /hydrating/.test(err.hint ?? '')) {
    await page.reload(); await page.wait({ time: 5 }); // retry once after hydration
  } else throw err;
}

Prevention

When it happens

Trigger: FEEDS_READ_JS executes successfully but the page-side script detects the feed data is not ready or an internal error occurred and returns { error: '...' }.

Common situations: Evaluating too early before Pinia hydration completes, slow network/SSR delays on /explore, rate limiting or anti-bot interstitials from the site, expired session causing the store to report an auth error.

Related errors


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