jackwener/OpenCLI · error · Error

Failed to extract ${targetLabel} export code.

Error message

Failed to extract ${targetLabel} export code.

What it means

Thrown by extractExportCode when the in-page export automation fails. The in-browser script clicks the Export button and the React/Vue target, polls the export dialog textarea until the code is complete and stable, and returns { ok:false, error } on any failure; the Node side then throws with the browser-reported reason (or this generic fallback message).

Source

Thrown at clis/uiverse/_shared.js:253

    const dialog = document.querySelector('[role="dialog"]');
    if (longest && longestLooksComplete) {
      return JSON.stringify({ ok: true, code: longest, length: longest.length, fallback: true });
    }

    return JSON.stringify({
      ok: false,
      error: dialog
        ? (targetLabel + ' dialog appeared, but the exported code never reached a stable complete state.')
        : (targetLabel + ' export dialog did not appear after clicking the export controls.'),
      dialogFound: Boolean(dialog),
      dialogText: dialog ? (dialog.innerText || '').slice(0, 200) : null,
      longestLength: longest.length,
    });
  })()`);

  const data = JSON.parse(raw);
  if (!data?.ok || typeof data.code !== 'string') {
    throw new Error(data?.error || `Failed to extract ${targetLabel} export code.`);
  }
  return data.code;
}

export function parseHtmlRootSignature(html) {
  const source = String(html || '').trim();
  const match = source.match(/^<([a-zA-Z0-9-]+)([^>]*)>/);
  if (!match) {
    return { tag: null, id: null, classes: [] };
  }

  const [, tag, attrs] = match;
  const idMatch = attrs.match(/\sid=["']([^"']+)["']/i);
  const classMatch = attrs.match(/\sclass=["']([^"']+)["']/i);
  const classes = classMatch ? classMatch[1].split(/\s+/).filter(Boolean) : [];
  return {
    tag: tag.toLowerCase(),
    id: idMatch ? idMatch[1] : null,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check the thrown message (data.error) for the specific sub-failure ('Could not find the export controls', 'did not appear', 'never reached a stable complete state') and act on it
  2. Ensure you are logged in inside the browser page so the Export controls render
  3. Increase polling tolerance: raise the 40x200ms loop or initial delays in the page.evaluate script for slow environments
  4. If the UI changed, update the selectors ('button' text 'Export', '[role="dialog"] textarea', target labels) in clis/uiverse/_shared.js to match the new markup

Example fix

// before
const code = await extractExportCode(page, 'react'); // times out on slow page
// after
try {
  var code = await extractExportCode(page, 'react');
} catch (e) {
  await page.waitForTimeout(3000); // let UI settle, retry once
  var code = await extractExportCode(page, 'react');
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify export controls exist before attempting extraction:
const hasExport = await page.locator('button', { hasText: 'Export' }).count();
if (!hasExport) throw new Error('Export button not rendered — are you logged in?');

Type guard

const isExportResult = (d) => d?.ok === true && typeof d?.code === 'string' && d.code.length > 0;

Try / catch

try {
  const code = await extractExportCode(page, target);
} catch (e) {
  const msg = e.message;
  if (msg.includes('Could not find the export controls')) {
    throw new Error('Not logged in or Export UI changed');
  }
  if (msg.includes('never reached a stable complete state')) {
    await page.waitForTimeout(5000);
    return extractExportCode(page, target); // retry once for slow renders
  }
  throw e;
}

Prevention

When it happens

Trigger: No Export button exists on the page (not logged in, or uiverse.io removed/renamed the control); the export dialog never opens after clicking; the dialog opens but the code never reaches a stable 'complete' state within ~8s of polling; the target (React/Vue) menu item never appears; the textarea read returns partial code for 40 consecutive checks.

Common situations: Scraping without authentication where Export is disabled; slow page/CPU causing the 200ms x 40 polling window to expire before the dialog renders; uiverse.io UI redesign moving the Export button or dialog markup; components whose exported code never matches the isCompleteExportCode heuristics (missing 'export default'/styled markers or template/style tags).

Related errors


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