jackwener/OpenCLI · error · CommandExecutionError
${command} selector drift${reason}
Error message
${command} selector drift${reason} What it means
requireRows throws this CommandExecutionError when the payload's ok flag is false, meaning the page loaded but the expected DOM structure was not found — the CSS selectors the scraper relies on no longer match. The optional payload.reason from the browser side is appended for detail.
Source
Thrown at clis/dribbble/utils.js:76
}
if (!/(^|\.)dribbble\.com$/i.test(url.hostname)) {
throw new ArgumentError('shot URL must use dribbble.com');
}
const match = url.pathname.match(/^\/shots\/(\d+)(?:-|\/|$)/);
if (!match) throw new ArgumentError('shot URL must match dribbble.com/shots/<id>');
return match[1];
}
export function requireRows(payload, command) {
if (!payload || typeof payload !== 'object') {
throw new CommandExecutionError(`${command} returned an unreadable browser payload`);
}
if (payload.empty) {
throw new EmptyResultError(command, payload.reason || `${command} returned no results`);
}
if (!payload.ok) {
const reason = payload.reason ? `: ${payload.reason}` : '';
throw new CommandExecutionError(`${command} selector drift${reason}`);
}
if (!Array.isArray(payload.rows)) {
throw new CommandExecutionError(`${command} returned a malformed rows payload`);
}
if (payload.rows.length === 0) {
throw new EmptyResultError(command, `${command} page loaded but no matching rows were found`);
}
return payload.rows;
}
export function requireRow(payload, command) {
if (!payload || typeof payload !== 'object') {
throw new CommandExecutionError(`${command} returned an unreadable browser payload`);
}
if (payload.empty) {
throw new EmptyResultError(command, payload.reason || `${command} was not found`);
}
if (!payload.ok || !payload.row) {View on GitHub (pinned to 49907e53dc)
Solutions
- Update the library to the latest version — selector fixes are typically shipped after site redesigns.
- Retry later or from a different network/IP if an anti-bot or consent page is the cause.
- Report the issue with payload.reason if updating does not fix it, so the selectors can be repaired.
- As a workaround, inspect the page manually to confirm whether the content still exists at all.
Example fix
// before
const rows = cli.rows('shots', payload); // 'shots selector drift'
// after
try {
rows = cli.rows('shots', payload);
} catch (e) {
if (String(e.message).includes('selector drift')) {
await upgradeLibrary(); // or notify maintainers with payload.reason
payload = await rerunBrowserCommand('shots');
rows = cli.rows('shots', payload);
} else throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
if (payload && payload.ok === false) {
console.warn('Scrape reported failure before requireRows:', payload.reason || 'no reason given');
} Type guard
function isSuccessfulPayload(p) {
return p != null && typeof p === 'object' && p.ok === true;
} Try / catch
try {
rows = requireRows(payload, 'shots');
} catch (e) {
if (e instanceof CommandExecutionError && /selector drift/.test(e.message)) {
logForMaintainers('shots', payload && payload.reason); // site markup likely changed
rows = []; // or fall back to a cached/alternate data source
} else throw e;
} Prevention
- Pin and regularly update the library; selector fixes follow Dribbble redesigns.
- Watch for anti-bot/consent interstitials and avoid hammering the site from datacenter IPs.
- Alert on 'selector drift' messages in production so outages are noticed immediately.
When it happens
Trigger: Dribbble redesigned their markup so the command's selectors miss; a bot-check/consent interstitial replaced the results; the page rendered an error or captcha state the scraper interprets as a failed run.
Common situations: Site layout changes after being away from updates, running an outdated version of the library against the live site, network conditions producing a partial page render, or hitting Dribbble from a datacenter IP that triggers an anti-bot wall.
Related errors
- Not a git repository
- Ctrip round-trip flight cards rendered but parser did not fi
- Ctrip train cards rendered but parser did not find required
- google images returned no extractable result rows; the page
- powerchina search
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b46b6784e4c550c4.
Report an issue: GitHub.