Debugging
Objectives
By the end of this lesson, you should be able to:
- Use
console.trace()to see exactly how a function was called - Use the
debuggerstatement with an attached debugger to pause execution - Debug a Node.js program directly from VS Code
💡 Why this matters:
console.loggets you surprisingly far, but sometimes a bug needs to be caught in the act, with real values inspected at the exact moment something goes wrong. This lesson covers the tools for that.
⚠️ A note on verification: every snippet and output in this lesson was actually run with Node.js.
console.trace()
function inner() {
console.trace("trace point");
}
function outer() {
inner();
}
outer();
Trace: trace point
at inner (/tmp/node103/tracedemo.js:2:11)
at outer (/tmp/node103/tracedemo.js:5:3)
at Object.<anonymous> (/tmp/node103/tracedemo.js:7:1)
...
console.trace() prints the full call stack at the point it’s called, exactly which function called which, in order. This answers “how did execution even get here?”, useful when a function is being called from an unexpected place, or more often than expected.
The debugger Statement
function calculateTotal(items) {
let total = 0;
for (const item of items) {
debugger;
total += item.price;
}
return total;
}
const items = [{ price: 10 }, { price: 20 }];
console.log(calculateTotal(items));
30
Run normally, with node calculateTotal.js, the debugger; line does absolutely nothing, it’s a no-op unless a debugger is actually attached to the process. Run with an attached debugger (covered next), execution pauses at that exact line every time it’s reached, letting you inspect every variable’s current value.
Debugging from VS Code
VS Code has a built-in Node.js debugger, no extension required. The simplest way to use it: open the file to debug, set a breakpoint by clicking to the left of a line number (a red dot appears), then press F5 (or use the Run and Debug panel) to start debugging. Execution pauses at each breakpoint, or at any debugger; statement, and VS Code shows every variable in scope, lets you step through code line by line, and lets you evaluate arbitrary expressions in the paused context.
This is significantly more powerful than scattering console.log calls everywhere, especially for a bug that only appears after several iterations of a loop, or deep inside a chain of function calls.
Debugging from the Command Line
node --inspect script.js starts Node with a debugging port open, then Chrome’s DevTools (visiting chrome://inspect) can attach to it directly, giving the same breakpoint and inspection capabilities as VS Code, just through the browser instead. This is useful in environments without VS Code available, or when debugging a program already running elsewhere.
Try It
- Add a
console.trace()call inside a function called from two different places, and confirm the trace shows both possible call paths across two separate runs. - Add a
debugger;statement inside a loop in VS Code, set a breakpoint on the same line instead, and step through several iterations, watching a variable’s value change. - Run a script with
node --inspect script.jsand connect to it fromchrome://inspect, confirming you can see the same breakpoint behavior. - Explain, in your own words, a situation where
console.logalone would be tedious to debug with, but a real debugger’s step-through capability would make it fast.
Recap
console.trace()prints the full call stack at a given point, showing exactly how execution reached it.debugger;does nothing without an attached debugger, but pauses execution there when one is attached.- VS Code’s built-in debugger (breakpoints, stepping, variable inspection) and
node --inspectwith Chrome DevTools are the two most common ways to actually debug a running Node.js program.
Next lesson: this module’s exercises, tying together everything about Node.js itself covered so far.