jackwener/OpenCLI · error · CommandExecutionError

gov-policy ${command} extractor returned no result rows

Error message

gov-policy ${command} extractor returned no result rows

What it means

Thrown by requireRows when an extractor's parsed rows are not a non-empty array — i.e. the page-level extraction produced nothing usable, typically because every result card was missing required fields (e.g. a title) or the container selectors matched nothing. It guards downstream formatting code from iterating undefined/null.

Source

Thrown at clis/gov-policy/utils.js:41

export function classifyExtractorFailure(command, result) {
    const sample = String(result?.sample || '').replace(/\s+/g, ' ').trim();
    const url = String(result?.url || '').trim();
    if (command === 'search' && EMPTY_RESULT_PATTERNS.some((pattern) => pattern.test(sample))) {
        throw new EmptyResultError('gov-policy search', sample ? sample.slice(0, 160) : undefined);
    }
    const context = [url && `url=${url}`, sample && `sample=${sample.slice(0, 160)}`]
        .filter(Boolean)
        .join('; ');
    throw new CommandExecutionError(
        `gov-policy ${command} page did not expose readable result rows`,
        context || 'The page structure may have changed or the page did not finish rendering.',
    );
}

export function requireRows(command, rows) {
    if (!Array.isArray(rows) || rows.length === 0) {
        throw new CommandExecutionError(
            `gov-policy ${command} extractor returned no result rows`,
            'The page structure may have changed or all result cards were missing required title fields.',
        );
    }
    return rows;
}

export function wrapBrowserError(command, error) {
    if (error instanceof ArgumentError || error instanceof EmptyResultError || error instanceof CommandExecutionError) {
        throw error;
    }
    throw new CommandExecutionError(`gov-policy ${command} browser extraction failed: ${error?.message ?? error}`);
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command to rule out incomplete page rendering
  2. Open the failing page URL in a browser and compare its markup to the extractor's expectations
  3. If the site markup changed, report/patch the adapter's selectors
  4. For the user: try a different query/page that still matches the known layout

Example fix

// before
const rows = extractCards(dom); // may be []
process(rows);
// after
const rows = requireRows('detail', extractCards(dom));
process(rows); // throws a descriptive CommandExecutionError instead of crashing later
Defensive patterns

Strategy: type-guard

Validate before calling

function rowsAreWellFormed(rows) {
  return Array.isArray(rows) && rows.length > 0 && rows.every(r => r && typeof r.title === 'string' && r.title.trim());
}
if (!rowsAreWellFormed(parsed)) throw new Error('Extractor output missing titled rows');

Type guard

function isNonEmptyRowArray(rows) { return Array.isArray(rows) && rows.length > 0 && rows.every(r => r != null && typeof r === 'object'); }

Try / catch

try {
  const rows = await govPolicyDetail(url);
} catch (err) {
  if (/extractor returned no result rows/.test(err.message)) {
    console.error('Page markup may have changed; verify selectors.');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling requireRows(command, rows) after an extractor returns [] or a non-array (e.g. null from a failed querySelectorAll mapping): site renamed card classes, or all cards filtered out by the title-field requirement.

Common situations: Detail/listing pages whose markup changed so the extractor's selectors return nothing, partially loaded pages where cards render without titles, scraping a page type the extractor was never built for.

Related errors


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