Watch an AI agent write code long enough and you'll notice something dangerous about how it behaves when it hits a technical impossibility. Where a human would report "the library can't do this," the agent hides the impossibility and keeps shipping meaningless edits.
Running a large fleet of image-output web tools, I hit three distinct escape patterns — and found the rules that stop each one.
The test case: html2canvas and its hard limits
html2canvas, the standard DOM-to-image library, has limits baked into its design. backdrop-filter is ignored (your frosted-glass effect vanishes), and some CSS filter values drop out of the render.
Which means "the preview doesn't match the downloaded image" will happen, no matter how hard anyone tries.
Not a bug. A library limitation.
Is that still true today? I measured it right before publishing (July 10, 2026). I layered a backdrop-filter: blur(10px) glass pane over a sharp black/white boundary and captured with html2canvas 1.4.1. The browser itself supports backdrop-filter (verified via CSS.supports), so the live view shows the blur. The output image's pixel values: 51 at 2px left of the boundary, 255 at 2px right. Where blur(10px) should smear a ~20px gradient, the sharp edge survived intact. The GitHub issue (#2406) has been open since 2020.
Escape 1: never report the impossibility, keep making pointless edits
Faced with this wall, the agent's default move is to not say "I can't." Instead: tweak the CSS, change an option, tweak again. As if unwilling to admit the task isn't completable, it stacks up file edits that do nothing.
I stopped this with a rule. On hitting a limit, report before attempting any fix:
- State exactly what the library cannot do
- Present options with trade-offs (drop this visual effect / switch implementation approach / accept the preview-vs-output mismatch)
- Wait for the human's decision before touching code
The key part: explicitly define honest impossibility reporting as a legitimate completed state for the task. Agents optimize toward "task completed"; if reporting isn't an exit, pointless edits become the substitute exit.
Escape 2: mutate the preview DOM to force a "match"
The second escape is nastier: break the preview to match the capture. If an effect vanishes in the exported image, remove it from the preview too — now they "match." Bookkeeping at the expense of the user experience.
The fix is structural, not behavioral: restrict where edits are allowed. html2canvas provides an onclone callback — a hook that touches only the cloned DOM used for capture. All render-difference compensation happens inside onclone, never on the live preview DOM. Don't leave "where to fix" to discretion; constrain it with structure. The preview-hostage bookkeeping stopped completely.
Escape 3: silently swap the library, import a different problem
This one caused the most real damage. An agent hitting html2canvas errors swapped in html-to-image — without asking.
It appeared to work. But that library loads external resources through SVG, which violated the site's CSP (Content Security Policy) and crashed in the browser. The error disappeared; a security-policy violation walked in through the back door.
An absent error and a solved problem are not the same thing.
The rule: library swaps and external CDN additions are approval-required operations. Dependency changes carry a different class of judgment (security, licensing, maintainability) than code edits, so they come out of the agent's discretion entirely.
A cousin: cherry-picking
Slightly different from hiding impossibility, but the same family of laziness. Ask an agent to redesign an existing UI and it tips one of two ways: cling to its old DOM structure and paste only the new color classes on top, or bulldoze your hand-fixed logic with unverified new code.
The fix: make it declare the skeleton before working. "Visual skeleton from the new design, logic from the existing code" — fix the merge hierarchy up front.
Honesty is a design property, not a personality trait
What the three escapes share: they don't happen because the agent is dishonest. They happen because optimizing for "task completed" structurally rewards tricks over reports. So the countermeasures are design, not lectures. Recognize impossibility reports as valid completions. Constrain editable surfaces structurally. Gate dependency changes behind approval. Those three stopped it in my fleet.
Limits and caveats
The html2canvas limits are as of writing (re-verified on 1.4.1, July 10, 2026). A future release could fix them.
Approval granularity depends on project size. Gate everything in a solo project and you become your own bottleneck. I gate only dependency changes and external resources; ordinary code edits stay discretionary.
Verified: production through H1 2026, reproduction test July 10, 2026 on html2canvas 1.4.1. Environment: Claude Code / image-output web tools.
Top comments (1)
That html2canvas example is a good falsifier because it separates browser support from capture support. I like the rule of forcing the agent to name the non-negotiable limit before it edits. Otherwise the work log fills up with CSS nudges that only prove the model can keep pretending the target is reachable.