Using the Debugger
This is a short guide I’ve written on the basics of debugging. It is supposed to be part of a much longer guide on writing reliable code in general, but if I waited until that was finished it’d never get uploaded. I’m making this guide as a resource for people who are fairly new to programming and may not know about (or haven’t time to learn about) the debugging tools in Roblox Studio.
The debugger consists of tools that let you run your code line by line to ensure it is working correctly. The basis of any debugging session is observing each line as it runs and making sure the version of the code in your head matches what you actually see happening.
When viewing a script in the editor, clicking the column to the right of line numbers will add a breakpoint. This appears as a solid red circle. If your code reaches this line while running, it will pause before running that line, and that line will be marked with a yellow arrow.
While paused, you can mouse over any symbol (variable) currently in scope to see its value. If you try to inspect a value which is not in scope, it will say ‘void’. This does not mean the value is nil!
You can also open the Watch window and switch to the Variables tab to see all the variable accessible from the current line.
Clicking Resume will make the game start running again. It will stop again if it hits another breakpoint or error. Note that it will not toggle your view back to the Client / Server mode it was previously in!
Clicking Step Into will run the current line and advance to the next one. If the next line to be run is inside of a function that is needed for the current line, it will advance “into” there.
Step Over is the same as Step Into except that it will always go to the very next line, it will not go inside of any functions in its way. It will still run the statements it skips over, however.
Step Out is used to leave a function, running all lines until the first line that is outside the current function. If you look at the Call Stack window, or the stack printout of an error, this function will go up one layer.
The best way to see the difference between each of these is to test them out. Also consider that you can add if statements with anything inside them just to act as a more specific place to put a breakpoint.
Interpreting errors
Script errors are always presented using the following format. The actual reason for the error is the first line in red. The blue lines below are the stack trace. Each line tells which function was called to get to the line that caused the error. This is essential when a function can be called from several different places, and can help you narrow down the problem. Without this stack trace, it is hard to debug errors that result from bad values being sent to your function.
(Note that the lines numbers don’t match here since I’ve made changes while writing)
In this trace, we can see that the error occurred on line 9 of NoobScript, in the function FairyRing. FairyRing was called by RingSpawner, and RingSpawner was called from line 20, which isn’t itself inside a function. The gray text at the right side of each blue line is the script and line number the listed function was called from. This gray text is actually present on all printouts, not just errors. You can click messages in the Output window to go the script and line they were sent from.
We can also stop immediately on an error by enabling Debug Errors On All Exceptions in the top bar. Be warned that this feature is bugged and needs to be toggled off then on again whenever you start studio.
Speaking of bugs, sometimes breakpoints will just not be hit even when they should. I have no idea why this is, but be warned. This is especially frequent when putting breakpoints in parallel code.
Not all code can be stepped into, or paused in at all. For example, most Roblox built-in functions cannot be paused in. This is known as “non-yieldable” code. Sometimes Remotes will not let you step into them, in this case you can try to catch the code running on the receiving side.
Finally, I highly recommend turning on this option in Studio Settings:
(Command bar operates on local state at breakpoint)
This lets you run code from the Command Bar using values and functions from the currently paused code. You never know when this will come in handy for testing.