Budgets and errors
Why a script can never freeze the editor or fail silently: the evaluation fences and the typed status model behind them.
Two promises hold everywhere scripts run: a script can never freeze or crash anything, and a failure is always a TYPED, explained status - never a silent wrong picture. This page is the model; the generated error codes and budgets pages carry every code and number, with worked failure examples you can reproduce.
The fallback rule
When a script fails on a frame - thrown error, tripped budget, refused write - that script commits NOTHING for the frame: every property it drives keeps its keyframed or panel value, the frame still renders, and other scripts are untouched. Nothing latches: the next frame evaluates afresh, so an error at frame 40 does not poison frame 41. The failing script's status chip in the Scripts panel carries the typed code, the message, the line where known, and - for failures inside cross-script pulls - the chain of who was evaluating whom.
Budgets, not trust
The runtime assumes scripts will misbehave and fences them with host-independent budgets: interpreter polls per script and per frame, a memory ceiling, and a call-stack guard (the numbers live on the budgets page). An infinite loop, a catastrophic regex, a memory bomb or runaway recursion each trip their fence and report a typed status - interrupted, out_of_memory, stack_overflow - while the editor keeps scrubbing.
Because the budgets count interpreter work rather than seconds, they are the SAME on every machine: a script that fits on your laptop fits on the farm. The editor adds one extra, local safety net - a wall-time watchdog around live previews - so even a pathological draft cannot wedge the app while you type; the watchdog is an editor convenience, never part of the render truth.
How the IDE presents trouble
- While typing, diagnostics mark the draft inline: syntax errors, banned globals, references outside the script's closure, a missing
return. - The live preview strip evaluates the draft in a scratch context and shows its value or its typed failure - an infinite loop appears as a FIXABLE budget issue pointing at the loop, not a spinner.
- After Apply, the truth is the script's status chip and the canvas. An erroring applied script shows its typed code and message in the panel, and every driven row quietly falls back to base.
The farm's failure policy
Renders never guess. Before anything queues, the export gate scans every script across the full frame range - one deterministic fold, the same evaluation the farm will run - and names the first failing frame per script. If a script still fails during a farm render, the job fails as a CONTENT error naming the frame, the script id and the typed code (and the failing component instance where one is involved), so the fix is a click away, and a retry cannot silently produce different pixels. A DISABLED script is honest everywhere the same way: it evaluates nowhere - editor, scan and farm alike.