AST Execution, Errors & Limits
This page explains what happens when an AST command runs and how to debug it when something goes wrong.
Execution flow
Section titled “Execution flow”- A command or event triggers the template
- Argument placeholders like
&p1and&tare resolved - Execution context is created with user, channel, and event data
- Input is tokenized
- Tokens are parsed into an AST
- The AST is evaluated
- Variables are written to memory, cache, or database if needed
- Final output is rendered and sent to chat
Why this matters
Section titled “Why this matters”Understanding the order helps you debug issues like:
- arguments not showing up where you expect
- missing variables
- branches running unexpectedly
- command references returning surprising results
- EventSub functions returning blank values in chat
Common error messages
Section titled “Common error messages”| Error Pattern | Meaning |
|---|---|
[Unknown function: name] | The function is not registered |
[Loop error: invalid loop syntax] | The loop syntax is malformed |
[Loop error: missing loop body] | The loop is missing {} |
[Parse error: expr] | The parser could not understand the expression |
Usage: $(func ...) | The function arguments are missing or invalid |
Limits and safety rules
Section titled “Limits and safety rules”Loop limits by plan
Section titled “Loop limits by plan”| Plan | Max nesting depth | Max iterations |
|---|---|---|
| Free | 2 | 25 |
| Premium | 3 | 50 |
| Pro | 4 | 100 |
Command reference limits
Section titled “Command reference limits”- max recursion depth:
5 - cycles are detected and stopped
Delay limits
Section titled “Delay limits”$(delay N)supports up to60seconds
Debugging checklist
Section titled “Debugging checklist”1. Start simple
Section titled “1. Start simple”Before building the full command, test a minimal version first.
"Hello $(user)!"2. Add one feature at a time
Section titled “2. Add one feature at a time”Good order:
- plain text
- arguments
- functions
- variables
- conditionals
- loops
3. Check initialization
Section titled “3. Check initialization”If a cache or database value might not exist yet, check it first:
*(^(#wins) ? %(#wins) : "no wins yet")4. Remember assignment is direct
Section titled “4. Remember assignment is direct”This is wrong if you want to increment:
%(#wins 1)This is correct:
%(#wins *(%(#wins) + 1))5. Remember EventSub context
Section titled “5. Remember EventSub context”Functions like $(cheer.amount) or $(reward.input) only work when the command runs from the matching event type.
Common gotchas
Section titled “Common gotchas”Blank cache value
Section titled “Blank cache value”If a # or ## variable expired, it comes back blank.
&t placement
Section titled “&t placement”&t must be last. You cannot define new &pN placeholders after it.
Loop overuse
Section titled “Loop overuse”If a loop can be replaced by a direct expression or command reference, prefer the simpler option.
Powerful actions in public commands
Section titled “Powerful actions in public commands”Commands using moderation, role, title, game, poll, or trigger actions should not be available to everyone.
Practical debugging mindset
Section titled “Practical debugging mindset”When a command breaks, ask these questions in order:
- Are my arguments correct?
- Did I create the variable before reading it?
- Am I assigning or incrementing?
- Am I in the right context for this function?
- Did I accidentally create recursion or loop complexity?
Safe testing tip
Section titled “Safe testing tip”Build the output first, then add side effects.
For example, test the text and branch logic before you add:
$(ban ...)$(vip ...)$(set.title ...)$(start.poll ...)$(trigger.send ...)
That makes it much easier to confirm the logic before the command starts changing real channel state.