jackwener/OpenCLI · error · Error
Could not locate a Uiverse preview element. Candidate data:
Error message
Could not locate a Uiverse preview element. Candidate data: ${JSON.stringify(result)} What it means
Thrown by locatePreviewElement when the in-page scoring pass finds no visible candidate element with a non-zero-size rect matching the component's HTML root signature (tag/id/classes, with fallback tags like label/button/a/div). The error embeds the top candidate data to help debug why nothing matched.
Source
Thrown at clis/uiverse/_shared.js:411
const tagNodes = queryAcrossRoots(tagName, 200);
for (const node of tagNodes.slice(0, 200)) {
collect(node, 'tag:' + tagName);
}
}
candidates.sort((left, right) => {
if (right.score !== left.score) return right.score - left.score;
if (left.rect.y !== right.rect.y) return left.rect.y - right.rect.y;
if (left.rect.x !== right.rect.x) return left.rect.x - right.rect.x;
return (left.rect.width * left.rect.height) - (right.rect.width * right.rect.height);
});
return JSON.stringify({ signature: sig, best: candidates[0] || null, candidates: candidates.slice(0, 5) });
})()`);
const result = JSON.parse(raw);
if (!result?.best?.rect?.width || !result?.best?.rect?.height) {
throw new Error(`Could not locate a Uiverse preview element. Candidate data: ${JSON.stringify(result)}`);
}
return result;
}
export function getDefaultOutputPath({ username, slug, suffix, extension }) {
const safeUsername = trimPathSegment(username).replace(/[^a-zA-Z0-9-_]/g, '-');
const safeSlug = trimPathSegment(slug).replace(/[^a-zA-Z0-9-_]/g, '-');
return path.join(os.tmpdir(), `opencli-uiverse-${safeUsername}-${safeSlug}-${suffix}.${extension}`);
}
export async function saveBase64File(base64, outputPath) {
const resolved = path.resolve(outputPath);
await fs.mkdir(path.dirname(resolved), { recursive: true });
await fs.writeFile(resolved, Buffer.from(base64, 'base64'));
return resolved;
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Log the Candidate data in the error: if best is null nothing matched, if rects are 0 it is hidden — adjust visibility waits accordingly
- Wait for rendering: page.waitForSelector or waitForTimeout/networkidle before calling locatePreviewElement
- If the root tag is a custom element, extend getPreviewFallbackTags in clis/uiverse/_shared.js to include it or its host container
- Check for iframes: switch to the component frame (page.frames) before locating the preview
Example fix
// before
const preview = await locatePreviewElement(page, html); // page still hydrating
// after
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000); // allow layout/animation
const preview = await locatePreviewElement(page, html); Defensive patterns
Strategy: try-catch
Validate before calling
await page.goto(componentUrl, { waitUntil: 'networkidle' });
await page.waitForTimeout(500); // ensure layout settled
const sig = parseHtmlRootSignature(html);
if (sig.tag && !['div','button','label','a','input'].includes(sig.tag)) {
console.warn('Custom-element root may not be locatable:', sig.tag);
} Type guard
const hasVisibleRect = (r) => r?.rect?.width > 0 && r?.rect?.height > 0;
Try / catch
try {
const preview = await locatePreviewElement(page, html);
} catch (e) {
if (e.message.startsWith('Could not locate a Uiverse preview element')) {
await page.waitForTimeout(2000); // late-rendering content
return locatePreviewElement(page, html);
}
throw e;
} Prevention
- Wait for rendering (networkidle + settle delay) before locating the preview
- Parse the Candidate data in the error message — it shows why nothing matched (null vs zero-rect)
- Handle iframe/shadow-root previews by extending traversal or switching frames
- Extend getPreviewFallbackTags for components whose root is an unusual tag
When it happens
Trigger: The page has no visible element matching the component's root signature and no usable fallback candidates (everything hidden, zero-size, or inside a dialog); getRawCode returned html whose root signature (e.g. an exotic custom element tag) matches nothing on the rendered page; the component renders inside an iframe the search doesn't traverse; the page didn't finish rendering when evaluated.
Common situations: Preview renders in a shadow root/iframe not reachable by the traversal; CSS keeps the root at opacity 0 or display none until user interaction; components whose root is a custom element (e.g. <my-widget>) not covered by fallback tags; race where screenshot/preview is taken before layout completes.
Related errors
- Ctrip round-trip flight DOM extraction returned malformed ro
- Ctrip round-trip flight cards rendered but parser did not fi
- Ctrip round-trip flight rows were missing required airline/f
- Ctrip package DOM extraction returned malformed rows
- Ctrip package cards rendered but parser did not find require
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c65d614f4bc9716b.
Report an issue: GitHub.