jackwener/OpenCLI · error · EmptyResultError

twitter trending

Error message

twitter trending

What it means

trending.js:54 validates the scrape result: the page.evaluate extracting [data-testid="trend"] cells must return a non-empty array. If the structure changed or nothing rendered, EmptyResultError('twitter trending', 'No trends found. The page structure may have changed.') is thrown so the caller knows the extractor, not the data, is likely at fault.

Source

Thrown at clis/twitter/trending.js:54

      const items = [];
      const cells = document.querySelectorAll('[data-testid="trend"]');
      cells.forEach((cell) => {
        const text = cell.textContent || '';
        if (text.includes('Promoted')) return;
        const container = cell.querySelector(':scope > div');
        if (!container) return;
        const divs = container.children;
        if (divs.length < 2) return;
        const topic = divs[1].textContent.trim();
        if (!topic) return;
        const catText = divs[0].textContent.trim();
        const category = catText.replace(/^\\d+\\s*/, '').replace(/^\\xB7\\s*/, '').trim();
        items.push({ rank: items.length + 1, topic, category });
      });
      return items;
    })()`);
        if (!Array.isArray(trends) || trends.length === 0) {
            throw new EmptyResultError('twitter trending', 'No trends found. The page structure may have changed.');
        }
        return trends.slice(0, limit);
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run once — slow rendering can beat the fixed waits; if it succeeds intermittently, increase the wait or use a proper waitForSelector('[data-testid="trend"]')
  2. Inspect the /explore/tabs/trending page and update the selector in trending.js if X changed data-testid="trend" to something else
  3. Confirm the account/region actually shows trends (some regions or settings show the 'Timeline' tab without trend items)
  4. Check you are not hitting a logged-out/login-wall variant of the page despite having a session

Example fix

// before (fixed waits)
await page.wait(3);
// after (wait for the actual elements)
await page.waitForSelector('[data-testid="trend"]', { timeout: 15000 });
Defensive patterns

Strategy: fallback

Validate before calling

// After evaluate, validate shape before use
const trends = await page.evaluate('/* scrape IIFE */');
if (!Array.isArray(trends) || trends.length === 0) {
  console.warn('No [data-testid="trend"] nodes found — page structure or load timing issue.');
}

Type guard

function isTrendList(value) {
  return Array.isArray(value)
    && value.length > 0
    && value.every((t) => t && typeof t.topic === 'string');
}

Try / catch

import { EmptyResultError } from '@jackwener/opencli/errors';
try {
  const trends = await getTrending();
} catch (e) {
  if (e instanceof EmptyResultError) {
    console.warn('No trends extracted; retrying with longer wait or reporting selector drift.');
    // fallback: retry once, then surface a warning instead of crashing
  } else throw e;
}

Prevention

When it happens

Trigger: page.evaluate returns undefined/null/non-array, or the trends array is empty because no elements matching [data-testid="trend"] were found after navigating to https://x.com/explore/tabs/trending and waiting ~5 seconds.

Common situations: X redesigned the trending markup (data-testid renamed/removed); page still loading or showing a login wall/interstitial after the fixed waits (page.wait(3) + page.wait(2)); region where trends are unavailable; A/B test variants; slow network so trends render after the wait window.

Related errors


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