pbakaus/impeccable · warning
[impeccable] capture failed, proceeding without screenshot:
Error message
[impeccable] capture failed, proceeding without screenshot:
What it means
Before dispatching a generate/steer event, the client captures the target element to a PNG blob via captureElementToBlob. If that capture throws (modern-screenshot failure, tainted canvas, layout mid-transition), the error is logged as 'capture failed, proceeding without screenshot:' and the flow continues without the image: non-annotated events were already sent before capture, annotated ones are sent afterwards minus the screenshotPath.
Source
Thrown at skill/scripts/live-browser.js:8039
async function captureAndEmit(el, basePayload, snapshot, rect) {
const hasAnnotations = snapshot && (snapshot.comments.length > 0 || snapshot.strokes.length > 0);
// Plain requests do not send a screenshot to the agent, so capture is
// presentation-only. Wait only for the helper to accept the event before
// starting CPU-heavy capture; this yields the browser task and prevents
// rasterization from delaying the fetch itself.
if (!hasAnnotations) {
basePayload.clientSentAt = Date.now();
await sendEvent(basePayload);
}
let screenshotPath;
let blob;
let paper;
try {
({ blob, paper } = await captureElementToBlob(el, snapshot, rect));
} catch (err) {
console.warn('[impeccable] capture failed, proceeding without screenshot:', err);
}
// Light up the shader overlay the moment capture is ready - no reason to
// wait for the upload to complete before the user sees something alive.
if (blob && state === 'GENERATING') {
showShaderOverlay(el, blob, rect, paper);
}
// Only upload + forward the screenshot when annotations (comments/strokes)
// are present. Without annotations the image is pure visual anchoring -
// it biases the model toward the current rendering and works against the
// three-distinct-directions brief.
if (blob && hasAnnotations) {
try {
const uploadRes = await fetch(
'http://localhost:' + PORT + '/annotation?token=' + encodeURIComponent(TOKEN) +
'&eventId=' + encodeURIComponent(basePayload.id),
{ method: 'POST', headers: { 'Content-Type': 'image/png' }, body: blob },
);
if (uploadRes.ok) {View on GitHub (pinned to f88b2837a7)
Solutions
- Check the request still succeeded — the event goes through without the screenshot
- Retrigger the generate to get a screenshot-backed run if visual anchoring mattered
- Serve images/fonts with permissive CORS so the canvas is not tainted
Defensive patterns
Strategy: fallback
Validate before calling
if (!el.isConnected) { sendWithoutScreenshot(); return; } // capture is pointless on detached elements Try / catch
try { ({ blob, paper } = await captureElementToBlob(el, snapshot, rect)); } catch (err) { console.warn('capture failed', err); } // event still dispatched without screenshotPath Prevention
- Do not trigger generate during hot-reload churn — wait for the DOM to settle
- Fix cross-origin asset CORS so canvas capture is reliable
- Design consumers to treat the screenshot as optional anchoring, never required input
When it happens
Trigger: modern-screenshot throws on the element (foreignObject-hostile content, cross-origin images without CORS, fonts still loading); capture racing a hot-reload remount of the target; capturing during page teardown.
Common situations: Dev-server hot reload swaps the element mid-capture; target contains cross-origin <img> without CORS headers; heavy pages where the rasterizer times out or OOMs.
Related errors
- [impeccable] Svelte ancestor crop capture failed, falling ba
- [impeccable] annotation upload failed:
- [impeccable] shader resume failed:
AI-assisted analysis of pbakaus/impeccable@f88b2837a7 (2026-08-18).
Data as JSON: /api/errors/c1380f587c3db74d.
Report an issue: GitHub.