jackwener/OpenCLI · error · EmptyResultError

No article content extracted — login session may have expire

Error message

No article content extracted — login session may have expired or the page renders an empty shell

What it means

The evaluator returned rows but rows[0].content was missing, non-string, or an empty string. Since content is the column this adapter exists to produce, an empty extraction is surfaced as EmptyResultError instead of silently returning [{content: ''}]. Xiaoe routinely renders an empty shell when the login cookie has expired, so the hint points at auth first.

Source

Thrown at clis/xiaoe/content.js:150

    try {
        await page.goto(url, { waitUntil: 'load', settleMs: 6000 });
        rows = await page.evaluate(buildContentScript());
    } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        throw new CommandExecutionError(
            `Failed to extract xiaoe content: ${message}`,
            'page may not have rendered or auth may be required',
        );
    }
    if (!Array.isArray(rows) || rows.length === 0) {
        throw new EmptyResultError(
            'xiaoe/content',
            'No rows returned from page evaluator (page structure may have changed)',
        );
    }
    const row = rows[0];
    if (!row || typeof row.content !== 'string' || row.content.length === 0) {
        throw new EmptyResultError(
            'xiaoe/content',
            'No article content extracted — login session may have expired or the page renders an empty shell',
        );
    }
    return rows;
}

export const contentCommand = cli({
    site: 'xiaoe',
    name: 'content',
    access: 'read',
    description: '提取小鹅通图文页面内容为文本',
    domain: 'h5.xet.citv.cn',
    strategy: Strategy.COOKIE,
    browser: true,
    args: [
        { name: 'url', required: true, positional: true, help: '页面 URL' },
    ],

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log back in to xiaoe / refresh the session cookies and retry
  2. Open the URL in a browser to confirm the article actually has content
  3. Check whether the content moved to a container outside CONTENT_SELECTORS and update the selectors
  4. Lower expectations: if the content is paywalled, a paid account is required
Defensive patterns

Strategy: fallback

Validate before calling

null

Type guard

null

Try / catch

try {
  const rows = await getXiaoeContent(url);
} catch (e) {
  if (e.name === 'EmptyResultError' && /login session may have expired/.test(e.message)) {
    await refreshXiaoeSession();
    return getXiaoeContent(url);
  }
  throw e;
}

Prevention

When it happens

Trigger: Rows extracted but no element matched with more than CONTENT_MIN_LENGTH (50) characters of text — e.g. logged-out shell page, empty fallback containers (main/#app/body) yielding short boilerplate text.

Common situations: Expired xiaoe login session (most common); the article/course really is empty or paywalled; CSS changed so text now lives in a container the selector chain misses with only a stub of text.

Related errors


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