Automation Limits
ScapieraScript runs in a secure sandbox. Every automation run has a fixed instruction budget, a wall-clock timeout, and an output line cap. Understanding these limits helps you write efficient automations.
Every automation runs inside a sandboxed Lua virtual machine that is created fresh for each run and discarded afterward. Three limits apply to every run:
| Limit | Value | What happens when exceeded | |---|---|---| | Instruction budget | 1,000,000 Lua instructions | Run terminates immediately with a budget error | | Wall-clock timeout | 15 seconds | Run terminates immediately with a timeout error | | Output buffer | 1,000 lines | Further output.print() calls are silently dropped |
If a run hits any limit, the partial changes already applied to the canvas are preserved β they are not automatically rolled back. Use Ctrl+Z to undo if you need to revert.
Key Parameters
| Name | Default | Description |
|---|---|---|
| Instruction budget | 1,000,000 | Maximum number of Lua virtual-machine instructions allowed per run. Roughly 1β2 seconds of pure computation on mid-range hardware. |
| Wall-clock timeout | 15 seconds | Maximum real elapsed time allowed per run, including all garden API call overhead. |
| Output buffer | 1,000 lines | Maximum number of lines captured from output.print() and output.warn() per run. Further calls are silently dropped and a truncation marker is appended. |
Wall-clock timeout
Regardless of instruction count, every run terminates after 15 seconds of real elapsed time.
The timeout is a safety net for automations that make many API calls β each garden.* call involves some overhead beyond pure Lua instructions. An automation that calls garden.find.byType() 10,000 times in a loop can exhaust the timeout even if it stays within the instruction budget.
Design your automations to process data in bulk rather than calling API methods repeatedly for each entity individually.
Use garden.find.all() or garden.find.byType() once to collect entities, then iterate over the result table β rather than calling garden.find.nearest() inside a loop for each entity.
Output buffer
The output console captures up to 1,000 lines per run. Once the buffer is full, additional output.print() and output.warn() calls are silently discarded β the run continues but output is lost.
For automations that process many entities, use conditional printing rather than logging every iteration: ``lua local count = 0 for _, entity in ipairs(entities) do -- process entity count = count + 1 end output.print('Processed ' .. count .. ' entities') ``
Call garden.find.all() or garden.find.byType() once before your loop to collect the full entity list, then iterate over the result table. Never call garden.find.nearest() or similar search methods inside a per-entity loop.
Check capabilities before using gated methods
Some garden. API methods are only available on specific subscription tiers β for example, garden.terrain. requires the Terrain module and garden.costs.* requires the Cost Estimation module.
Calling a method you do not have access to produces a capability error. To write automations that work gracefully across different account types, check capabilities before branching: ``lua if garden.capabilities.has('terrain') then local elevation = garden.terrain.elevationAt({x=0, y=0}) output.print('Elevation: ' .. elevation) else output.warn('Terrain module not available on this account') end ``
Capability names: '2d-drawing', '3d', 'cost-estimation', 'terrain', 'lighting', 'irrigation', 'structure-editor', 'plant-placement'.
If you are sharing automations with other users who may have different subscription tiers, wrap tier-specific calls in capability checks so the automation degrades gracefully rather than erroring.
Check capabilities before using gated methods
Some garden. methods are only available when the active subscription includes the corresponding module. For example, garden.terrain.** requires the Terrain module and garden.costs.** requires Cost Estimation. Calling a method your account does not have access to produces a capability error immediately. Use garden.capabilities.has()** to check before branching, so the automation degrades gracefully instead of erroring for users on different plans.
If you share automations with colleagues who may have different subscription tiers, wrap tier-specific calls in capability checks. Supported capability names: '2d-drawing', '3d', 'cost-estimation', 'terrain', 'lighting', 'irrigation', 'structure-editor', 'plant-placement'.
Handle partial runs after a limit is hit
When a run is terminated by any limit, partial canvas changes are preserved β they are not automatically rolled back. If your automation placed 200 plants before the instruction budget ran out, those 200 plants remain on the canvas. Press Cmd+Z (Mac) / Ctrl+Z (Windows) immediately after a failed run to undo all changes from that run in one step. Inspect the output panel first to understand how far the automation progressed before reverting.
A run that is terminated mid-way does not automatically undo its changes. Always check the canvas after a limit error and use Cmd+Z / Ctrl+Z if you need to revert to the state before the run.
The sandbox strips dangerous Lua libraries (os, io, require, package, loadfile, dofile) before your script runs. This is by design β automations cannot access the filesystem, the network, or any browser API outside the garden namespace.
Frequently Asked Questions
What happens to canvas changes if a run is terminated by a limit?
Any entity changes made before the limit was hit are preserved on the canvas β they are not automatically undone. Press Cmd+Z (Mac) or Ctrl+Z (Windows) to undo all changes from the run in a single step. Check the output panel first to see how far the automation progressed before deciding whether to revert.
Can I see how much of the run budget my automation has used?
Yes. Call garden.debug.budget() anywhere in your script. It returns a table with the current run's counters β reads, mutations, creations, and elapsedMs (elapsed milliseconds) β or nil when called outside a budget-tracked run. Use these counters to find which part of your script is doing the most work.
Why is my automation hitting the timeout even though the loop looks fast?
Each garden. API call involves overhead beyond pure Lua instruction counting β the call bridges from the Lua VM into the editor's JavaScript environment. An automation calling garden.find. or garden.measure.* thousands of times can easily exhaust the 15-second wall-clock timeout even with a low instruction count. Restructure to call bulk query methods once before the loop, then iterate over the cached result table.
Why did output stop appearing partway through my run?
The output buffer holds a maximum of 1,000 lines. Once full, further output.print() and output.warn() calls are silently dropped. A truncation marker is appended at the 1,000-line point so you can tell output was lost. Switch to counting-and-summarizing patterns rather than logging every iteration.
What happens if I call a garden.* method my subscription does not include?
The call produces a capability error immediately and the run is terminated at that point. Use garden.capabilities.has('capability-name') to check before calling tier-specific methods, so your automation degrades gracefully for users on different plans rather than erroring.