Manual

Manual · The book

Debugging

Breakpoints, stepping, the query log — on real data.

Debug is Run, plus truth

The Debug button starts the same application against the same development database — with the debugger attached. It is made to be usable on real data, because the bug you are hunting lives there.

Breakpoints

Click the gutter. A breakpoint can carry a condition (record.total > 10000) and a hit count — the crash on the 400th row is reachable without 399 clicks of Continue. A forgotten pause() in a script refuses the build, so it cannot ship.

A breakpoint set in the gutter on line 4, before the run starts
Set before anything runs: the gutter marks the line, and the console says which line of which script is now armed.

Stepping and seeing

Step, Step Over, Step Out. Variables open up — records show their fields, arrays their elements. The script, its line, and the whole scope: what you would ask a colleague to describe over the phone, on screen.

Stopped at a breakpoint: the line, the scope, the step buttons
Stopped at line 4, with the script named, the whole scope open underneath and the step buttons where the sentence is.

The query log

Every query the running application makes, in order, with its row count and time. This is where an N+1 loop becomes visible: four thousand one-row queries in a straight column are unmistakable — and the fix (count(), a narrowed query, a computed field) is usually one line. The lazy attachment reads appear here too, so a list secretly opening documents is just as visible.

The query log: every query with rows, time and the script that caused it
Every query with its rows and its milliseconds — and the script and line that asked for it, which is what turns a suspicion into an address.

Watching one expression, and who called this

Two more tabs beside the variables. Watch takes an expression — invoice.customer.name, form.list.count() — and evaluates it wherever the script stops, every time it stops: the way to follow one value through a loop without opening the scope at each pass. Call stack answers the other question — how did we get here — and says so plainly when the answer is “nobody”: an event script called by the window itself is the top of its own stack.

The Watch tab with an expression typed in and its empty state explained
An expression, evaluated at every stop — and an empty list that says what it is for rather than sitting there blank.
The Call stack tab showing one frame and the sentence that nothing called it
One frame, and the honest sentence under it: nothing called this, the script starts here.

The post-mortem

When a script throws, the debugger shows the moment of death — the line, the file, the variables as they were — even though nothing was paused. One look usually replaces a quarter of an hour of guessing.