Debug code
Pause with a debugger
Set a breakpoint, inspect values and scope, step through control flow, and change no code until the state is understood.
10 minute lesson
Print debugging costs one edit-and-rerun cycle per question. A debugger lets you stop execution before the wrong result spreads, then ask as many questions as you want about that frozen moment. Inspect actual runtime state instead of adding many speculative logs.
Neither tool is always right. Logs win in production and across many requests. A debugger wins when you have one reproducible failure and need to see state you did not think to print.
Start Node with the inspector
Start a Node process with the inspector:
node --inspect-brk app.mjs
--inspect-brk pauses on the first line, so you have time to set breakpoints before any code runs. Plain --inspect starts executing immediately. Open chrome://inspect in Chrome and click your process under Remote Target — DevTools attaches to the paused process.
Attach DevTools, pause at the relevant function, then work a fixed loop:
1. set a breakpoint on the line before the suspected failure
2. resume, wait for the pause
3. read local values and the call stack — is the state what you assumed?
4. step over (next line) or step into (enter the call), deliberately
The payoff moment: a variable holds a value you were sure it couldn’t. That is the assumption the whole bug was hiding behind, and staring at source code would never have caught it. You can also drop a debugger statement in the code; any attached inspector pauses there.
Conditional breakpoints
When a function runs 500 times and fails once, a plain breakpoint is torture. Right-click the breakpoint and add a condition like item.price === undefined. Execution pauses only on the failing iteration, replacing the whole log-and-grep cycle.
The safety rule
Do not attach an unauthenticated remote debugger to a public interface. The inspector protocol can evaluate arbitrary code — debuggers can execute code with process authority. Keep the inspector bound to 127.0.0.1, and tunnel over SSH when you must debug a remote machine.
And change no code until the state is understood. The debugger’s value is observing the system exactly as it is; the moment you start editing mid-session, you are experimenting, and that belongs in the change-one-variable workflow.
Lesson completed