jackwener/OpenCLI · error · CommandExecutionError

AIbase daily selector drift: ${reason}

Error message

AIbase daily selector drift: ${reason}

What it means

toRows throws this CommandExecutionError when the extraction script reports payload.ok === false, meaning the page loaded but the expected DOM selectors matched nothing. The reason comes from the script ('selector-missing') or defaults to 'selector-drift', and the error detail may include the page title to help diagnose what actually rendered.

Source

Thrown at clis/aibase/news.js:64

          seen.add(url);
          rows.push({
            rank: rows.length + 1,
            title: anchor.innerText || anchor.textContent || '',
            url,
          });
        }
        return { ok: true, rows };
      })()
    `;
}

function toRows(payload, limit) {
    if (!payload || typeof payload !== 'object') {
        throw new CommandExecutionError('AIbase daily page returned an unreadable payload');
    }
    if (!payload.ok) {
        const reason = typeof payload.reason === 'string' && payload.reason.trim() ? payload.reason.trim() : 'selector-drift';
        throw new CommandExecutionError(
            `AIbase daily selector drift: ${reason}`,
            payload.title ? `Page title: ${payload.title}` : undefined,
        );
    }
    const rows = (Array.isArray(payload.rows) ? payload.rows : [])
        .map((row, index) => ({
            rank: index + 1,
            title: normalizeText(row.title),
            url: normalizeText(row.url),
        }))
        .filter((row) => row.title && row.url);
    if (rows.length === 0) {
        throw new EmptyResultError('aibase news', 'AIbase daily page loaded, but no article rows with title and URL were extracted.');
    }
    return rows.slice(0, limit).map((row, index) => ({ ...row, rank: index + 1 }));
}

async function loadAibaseNews(page, args) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check the Page title detail in the error to identify what page actually rendered (captcha, consent wall, redesign).
  2. Retry later — if it's a temporary interstitial or empty daily edition it may resolve.
  3. Update the CSS selectors in buildExtractAibaseNewsJs to match the site's current DOM (inspect the live page).
  4. Clear/refresh the browser session (opencli aibase login) if a stale session or cookie wall is causing the alternate page.

Example fix

// before
const anchors = Array.from(document.querySelectorAll('.bg-white .grid a[href], a[href*="/zh/daily/"]'))
// after (selectors updated to the site's new markup)
const anchors = Array.from(document.querySelectorAll('.daily-list a.article-link, a[href*="/zh/daily/"]'))
Defensive patterns

Strategy: fallback

Validate before calling

null

Type guard

function hasExpectedRows(payload) {
  return !!payload && typeof payload === 'object' && payload.ok === true && Array.isArray(payload.rows) && payload.rows.length > 0;
}

Try / catch

try {
  await runCommand(['aibase', 'news']);
} catch (e) {
  if (e instanceof CommandExecutionError && e.message.includes('selector drift')) {
    console.error('Site markup changed; check Page title detail and update selectors');
  } else throw e;
}

Prevention

When it happens

Trigger: The injected script finds zero anchors matching '.bg-white .grid a[href]' or 'a[href*="/zh/daily/"]' and returns {ok:false, reason:'selector-missing', ...}; or returns ok:false with any other reason.

Common situations: AIbase redesigned its daily page (class names/structure changed); an anti-bot or consent interstitial replaced the article grid; the page served a regional variant or an empty daily edition with no articles; A/B tests altering markup.

Related errors


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