jackwener/OpenCLI · error · CommandExecutionError

google images returned no extractable result rows; the page

Error message

google images returned no extractable result rows; the page layout may have changed.

What it means

This CommandExecutionError is thrown when the google images command extracts zero result rows and the page-state inspection finds no CAPTCHA/consent and no explicit 'no results' indicator. It signals that Google's DOM layout likely changed so the row-extraction selectors no longer match anything.

Source

Thrown at clis/google/images.js:449

        const pageSize = Math.max(limit, 20);
        const url = `https://www.google.com/search?tbm=isch&q=${encodeURIComponent(query)}&hl=${lang}&num=${pageSize}`;

        await runBrowserStep('google images navigation', () => navigateGoogleImages(page, url));
        try {
            await page.wait({ selector: '#rso img, #islrg img, #center_col img, #rcnt img', timeout: 8 });
        }
        catch {
            await page.wait(2).catch(() => {});
        }

        const rows = await runBrowserStep('google images extraction', () => evaluateGoogleImageRows(page, limit, resolveOriginal));
        if (rows.length === 0) {
            const state = await runBrowserStep('google images page-state inspection', () => evaluateGoogleImagesPageState(page));
            if (state.captchaOrConsent) {
                throw new CommandExecutionError('google images is blocked by a Google CAPTCHA/consent/interstitial page.');
            }
            if (!state.explicitNoResults) {
                throw new CommandExecutionError('google images returned no extractable result rows; the page layout may have changed.');
            }
        }
        return normalizeImageRows(rows, query, limit);
    },
});

export const __test__ = { command, evaluateGoogleImageRows, extractGoogleImageRows, inspectGoogleImagesPage, normalizeImageRows, navigateGoogleImages };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command once — transient slow loads can produce an empty extraction before render completes
  2. Update the extraction selectors in evaluateGoogleImageRows to match the current Google Images DOM
  3. Check Google's page manually in a browser to confirm whether results exist for the query
  4. Add a wait/retry for result containers to appear before declaring the layout changed

Example fix

// before
const rows = await evaluateGoogleImageRows(page, limit, resolveOriginal);
// after
await page.waitForSelector('[data-attrid], img[src^="http"]', {timeout: 10000}).catch(() => {});
const rows = await evaluateGoogleImageRows(page, limit, resolveOriginal);
Defensive patterns

Strategy: retry

Validate before calling

// no caller-side validation; ensure the page is fully loaded before invoking
await page.waitForLoadState('networkidle');

Type guard

function hasResults(wrapper) {
  return wrapper != null && Array.isArray(wrapper.items) && wrapper.items.length > 0;
}

Try / catch

try {
  const rows = await imagesCommand.func(args);
} catch (e) {
  if (e.message.includes('layout may have changed')) {
    await page.reload({waitUntil: 'networkidle'});
    return imagesCommand.func(args); // one retry after reload
  }
  throw e;
}

Prevention

When it happens

Trigger: evaluateGoogleImageRows returns an empty array, evaluateGoogleImagesPageState reports captchaOrConsent=false and explicitNoResults=false — i.e. an unrecognized page structure, typically after a Google Images markup change or an incomplete page load.

Common situations: Google ships a new Images DOM and the scraper selectors become stale; the results page is only partially rendered because scripts didn't finish before evaluate ran; locale variants of Google Images use different markup; network flakiness leaves a blank shell page.

Related errors


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