heygen-com/hyperframes · error
--zoom selector matched no element: ${target.selector}
Error message
--zoom selector matched no element: ${target.selector} What it means
Thrown by resolveCropRegion() when a --zoom target of kind 'selector' is resolved but document.querySelector(selector) returned null at capture time — the element did not exist in the DOM when the frame was sampled. The pipeline deliberately fails loud rather than silently falling back to a full-frame crop, because a silent fallback would produce a misleading zoom that looks like a bug elsewhere. The offending selector is included.
Source
Thrown at packages/cli/src/capture/captureCompositionFrame.ts:468
// clamping leaves a pixel-wide remnant. Either way the crop would be a sliver
// that tells an agent nothing, so the final clamped region is what's guarded
// and callers skip the frame on null. Explicit x,y,w,h regions stay literal.
const MIN_CROP_REGION_PX = 8;
export async function resolveCropRegion(
page: ZoomSelectorPage,
target: ZoomTarget,
canvas: CropCanvas,
paddingPx = DEFAULT_ZOOM_PADDING_PX,
): Promise<CropRegion | null> {
if (target.kind === "region") return clampCropRegion(target.region, canvas);
const bbox = await page.evaluate((selector) => {
const element = document.querySelector(selector);
if (!element) return null;
const rect = element.getBoundingClientRect();
return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
}, target.selector);
if (!bbox) throw new Error(`--zoom selector matched no element: ${target.selector}`);
const region = padCropRegion(bbox, canvas, paddingPx);
if (region.width < MIN_CROP_REGION_PX || region.height < MIN_CROP_REGION_PX) return null;
return region;
}
export interface CropCapturePage {
viewport(): { width: number; height: number; deviceScaleFactor?: number } | null;
setViewport(viewport: {
width: number;
height: number;
deviceScaleFactor?: number;
}): Promise<void>;
screenshot(options: { clip: CropRegion; type: "png"; omitBackground: true }): Promise<Uint8Array>;
}
/**
* Capture a high-density crop of `region`: raise `deviceScaleFactor` to
* `scale`, take a clip screenshot, then restore the original viewport.View on GitHub (pinned to c2996c8626)
Solutions
- Verify the selector matches at the capture timecode: open the composition in a browser at that frame and run document.querySelector('<selector>') in devtools.
- Use a selector that is stable across the timeline, or switch to an explicit region (--zoom x,y,w,h) if the element moves.
- If the element is shadow-DOM scoped, use a selector that pierces it or restructure the composition.
- Confirm the element exists at the exact frame being captured (not just at t=0).
Example fix
// before — selector does not match at capture time --zoom .stat-value // element only appears after a fragment reveal // option A: use a stable selector --zoom #hero-title // option B: use an explicit region (in px) --zoom 120,80,640,360
Defensive patterns
Strategy: validation
Validate before calling
// Before capture, verify the selector resolves at the target timecode in a preview run.
const exists = await page.evaluate((sel) => !!document.querySelector(sel), selector);
if (!exists) {
throw new Error(`Selector not present at this timecode: ${selector}`);
} Try / catch
try {
await resolveCropRegion(page, target, canvas);
} catch (err) {
if (/--zoom selector matched no element/i.test((err as Error).message)) {
// fall back to an explicit region or skip the frame
}
throw err;
} Prevention
- Use stable, ever-present selectors for --zoom targets.
- When a target only appears after a fragment reveal, sample at a later timecode or use an explicit region.
- For shadow DOM, use piercing selectors or restructure the composition.
When it happens
Trigger: A --zoom selector target is evaluated via page.evaluate; document.querySelector(target.selector) returns null. Happens when the element is conditionally rendered, behind a fragment that hasn't mounted yet, mistyped, or removed from the composition since the selector was authored.
Common situations: Selector references a class/ID that was renamed; element exists only after a fragment reveal that hasn't fired at the sampled timecode; typo in the selector; element is inside a shadow DOM that querySelector can't cross; element only appears in a different slide/scene.
Related errors
- --shot: --selector '${scopeSelector}' matched no element.
- [handler] chunk URI at index ${i} is empty
- PLAN_V2_INTEGRITY_UNRECOVERABLE
- [s3Transport] expected s3:// URI, got: ${JSON.stringify(uri)
- [s3Transport] missing key in s3 URI: ${JSON.stringify(uri)}
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/220574da833ccc40.
Report an issue: GitHub.