pbakaus/impeccable · error · Error
Ancestor crop failed to produce a PNG blob
Error message
Ancestor crop failed to produce a PNG blob
What it means
After drawing the ancestor crop onto an offscreen canvas, the script converts it to a PNG via crop.toBlob and throws if the resulting blob is null. HTMLCanvasElement.toBlob yields null when the canvas is tainted (cross-origin content drawn without CORS), the canvas has zero size, or the browser fails the encode.
Source
Thrown at skill/scripts/live-browser.js:8156
const captureRoot = findShaderProxyCaptureRoot(el);
if (!captureRoot) throw new Error('No painted ancestor for Svelte shader proxy');
const rootCanvas = await ms.domToCanvas(captureRoot, opts);
const S = opts.scale;
const er = el.getBoundingClientRect();
const rr = captureRoot.getBoundingClientRect();
const sx = (er.left - rr.left) * S;
const sy = (er.top - rr.top) * S;
const sw = er.width * S;
const sh = er.height * S;
if (sw <= 0 || sh <= 0) throw new Error('Selected element has no visible capture rect');
const crop = doc.createElement('canvas');
crop.width = Math.max(1, Math.round(sw));
crop.height = Math.max(1, Math.round(sh));
const cctx = crop.getContext('2d', { willReadFrequently: true });
cctx.drawImage(rootCanvas, sx, sy, sw, sh, 0, 0, crop.width, crop.height);
const paper = dominantRgb01(cctx, crop.width, crop.height) || averageRgb01(cctx, crop.width, crop.height);
const blob = await new Promise((res) => crop.toBlob(res, 'image/png'));
if (!blob) throw new Error('Ancestor crop failed to produce a PNG blob');
return { blob, paper };
}
async function captureElementToBlob(el, snapshot, rect) {
try { if (document.fonts?.ready) await document.fonts.ready; } catch {}
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
let annotNode = null;
let savedPosition = null;
if (hasAnnotations) {
const pos = getComputedStyle(el).position;
if (pos === 'static') {
savedPosition = el.style.position;
el.style.position = 'relative';
}
annotNode = buildAnnotationsForCapture(rect, snapshot);
el.appendChild(annotNode);
}
try {View on GitHub (pinned to 2bc2879276)
Solutions
- Serve cross-origin images with CORS headers and load them with crossorigin="anonymous" so the canvas stays untainted
- Proxy remote assets through the local dev server (same origin) before capture
- Confirm the crop canvas has non-zero dimensions (zero-area canvases can yield null blobs)
- Retry the capture; if it persists, fall back to capturing a smaller same-origin region
Example fix
// before
const blob = await new Promise((res) => crop.toBlob(res, 'image/png'));
if (!blob) throw new Error('Ancestor crop failed to produce a PNG blob');
// after
const blob = await new Promise((res, rej) => crop.toBlob(b => b ? res(b) : rej(new Error('toBlob returned null (tainted or zero-size canvas?)')), 'image/png')); Defensive patterns
Strategy: fallback
Validate before calling
// detect taint before exporting
try { cctx.getImageData(0, 0, 1, 1); } catch { console.warn('canvas tainted; PNG export will fail'); } Try / catch
const blob = await new Promise((res) => crop.toBlob(res, 'image/png'));
if (!blob) {
console.warn('PNG export failed — canvas likely tainted; retrying with same-origin assets');
return null; // fall back to no-background mode
} Prevention
- Load all images/fonts with crossorigin="anonymous" and serve them with CORS headers
- Proxy third-party assets through the same origin before rendering pages you'll capture
- Verify crop canvas dimensions are non-zero before toBlob
- Wrap toBlob in a promise that rejects on null so failures are diagnosable
When it happens
Trigger: crop.toBlob('image/png') calls back with null — commonly because rootCanvas was produced from a capture root containing cross-origin images/fonts that tainted the canvas, so drawImage propagated a taint and toBlob cannot export.
Common situations: Page embeds third-party images without crossorigin attributes; fonts/images from another origin without CORS headers; screenshotting a region containing an iframe with foreign content.
Related errors
- [impeccable] Svelte ancestor crop capture failed, falling ba
- Selected element has no visible capture rect
AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08).
Data as JSON: /api/errors/2523dfa106c48b8f.
Report an issue: GitHub.