Two domed stacks of wheat cast long shadows across a sunlit field.
Claude Monet, Stacks of Wheat (End of Summer), 1890-91
back
bugs / svgator / building in public / svg / debugging 0

two clip paths walk into a group and never leave

how my ai broke an animation editor at 2am, and then helped me find out why

clip a and clip b endlessly swapping the top spot inside one group group clipPath a · rounded frame clipPath b · reveal bg rect (just vibing) "after you" "no, after you" chrome: out of memory
moves so far: 0 · in the real editor this happens about 900 times a second

so it’s monday night and i’m in a challenge i signed up for like four hours ago. svgator x contra, animated templates, ten grand on the table, deadline tomorrow. and i’m not even drawing in the editor like a normal person. i’ve got an ai plugged straight into svgator through their mcp, so i talk and it builds, keyframes appearing out of nowhere like some radio station in the desert only i can hear at 2am. it’s beautiful. it’s the future. and then the tab dies.

not a crash with a nice little error. the fan spins up, the page goes grey, chrome says out of memory and goes quiet. i reload. same thing. ok.

taste everything

here’s the thing about bugs, they’re like a kitchen at 11pm, everybody’s tired and something’s burning and nobody can tell you what. you have to taste everything. so that’s what we did. made a folder called “zz test projects (safe to delete)” and started cutting the template in half, and in half again, like taking ingredients out of a sauce until it stops tasting wrong.

imagestextbuttonslabelsclip aclip bbg
dead
imagestextbuttonslabelsclip aclip bbg
alive
imagestextbuttonslabelsclip aclip bbg
dead
imagestextbuttonslabelsclip aclip bbg
alive
the sauce, reduced. everything else can stay or go, doesn't matter. two clips in the same group = dead tab.

and it gets down to almost nothing. a background rectangle and two clip paths. one rounded frame, one reveal that grows and shrinks. nothing even uses them. that’s it, that’s the whole project, and it kills the browser. take one clip away and it opens fine. put it back, dead. we even tried two boring static clips with square corners and no animation. dead. two is the magic number and nobody told me.

the watchdog

so now i’m curious, the bad kind of curious, the kind that keeps you up. the editor is just javascript the site sends to my own browser, so you can read it, it’s right there. 1.4 megabytes on one line, minified into alphabet soup. but you can’t catch a hang by reading, because a hung page can’t tell you anything, it’s frozen, it’s a guy staring at a wall.

so we built a watchdog. a little heartbeat that ticks every tenth of a second, and anything that runs while the heartbeat is stuck for more than four seconds gets stopped and has to say where it was standing.

a heartbeat line that goes flat when the editor freezes, then the watchdog fires heartbeat every 100ms frozen. 1s… 2s… 3s… 4s… watchdog: freeze!
bringToFront               editor.js
p  (layers panel render)   editor.js
render                     editor.js
flushJobs                  vue.global.prod.js
what it confessed. trimmed, but those are the real names.

load the broken project into an already-open editor with the watchdog on. the page doesn’t die this time. the watchdog grabs it by the collar and it gives up a stack trace. and the stack trace says: the layers panel. the little list on the left with the folder icons. that’s the killer.

after you, no after you

every time the layers panel draws itself, it wants clip paths to sit at the top of their group. fine, tidy, i respect it. so while it’s drawing, it reaches into the actual document and moves the clip up. but moving something in the document is a change, and a change means draw again.

one clip

draw 1bgb→ move b up →bbg
draw 2bbg→ already on top
settles. everybody goes home.

two clips

draw 1abbg→ move b up →babg
draw 2babg→ move a up →abbg
draw 3same as draw 1. forever.
never settles. tab runs out of air.
with two, moving one clip up pushes the other one down, so the next draw moves that one, and so on.

two guys in a doorway going “after you” “no after you” until the building runs out of air. we counted how many times things got moved while each test project loaded.

one clip1
one static clip1
clips in own groups2
two clips3,757
two static clips3,561
two clips, square3,743
two clips, swapped3,526
clip + mask5,185
moves while loading, to scale. the red ones were still going when the watchdog stopped them after about 4 seconds.

the framework they use has a safety check for exactly this, “you’re updating in a loop, stop”, but it only exists in the developer build. in production it just keeps going until chrome pulls the plug.

proof it’s really that and nothing else: we told just that one move to quit, everything else untouched, and the crashing projects opened like nothing ever happened.

don’t move the furniture while you’re drawing the room

the fix is small and kind of poetic. sort the clips to the top in the list you show, leave the real document alone. if the order has to be real, fix it once when the file loads, not on every frame.

and the workaround if you’re building with the mcp right now: one clip per group. each clip lives inside the group it cuts, which is how the editor makes them itself anyway.

crashes

canvas
├─ clipPath a
├─ clipPath b
└─ everything else
two clips, one container

works

canvas
├─ group (clipped by a)
│  ├─ clipPath a
│  └─ frame stuff
└─ group (clipped by b)
   ├─ clipPath b
   └─ reveal stuff
one clip per container

my templates went back to that and life is good again.

the bug report got bounced for being too much of a bug report

wrote it all up, the test projects, the whole bisection table, the stack, a tiny script that recreates the swap, the suggested fix, sent it to svgator. first email bounced lol.

mail delivery subsystem · 2:13 am
message blocked. 1 attachment is a file type that isn't allowed (.js).
the simulation script. it just moves letters around in a list. put it inside the doc instead and sent it again.

what i keep thinking about is how weird and good this moment is. i signed up to make some animations. the ai was building them. the ai was also the one that broke the editor, because it built something no human clicking buttons ever would. and then the ai and me hunted the bug down together at 2am through a wall of minified code. nobody planned that part. that’s the part i’ll remember.

anyway. two clip paths walked into a group. still in there, probably. holding the door for each other.

irdi zeneli