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
- Check the Page title detail in the error to identify what page actually rendered (captcha, consent wall, redesign).
- Retry later — if it's a temporary interstitial or empty daily edition it may resolve.
- Update the CSS selectors in buildExtractAibaseNewsJs to match the site's current DOM (inspect the live page).
- 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
- Read the reason and Page title in the error detail to identify interstitials vs redesigns
- Pin/re-test scraping commands after site redesigns
- Keep extraction selectors resilient (multiple fallback selectors)
- Retry later for temporary interstitials or empty daily editions
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
- Not a git repository
- ${label} returned an unexpected payload shape; expected an a
- AIbase daily page returned an unreadable payload
- aibase news
- Working tree not clean: ${status}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8c26010bcbda78ed.
Report an issue: GitHub.