After this lesson, you will be able to: Read a stack trace, set breakpoints in VS Code, reproduce bugs reliably, and find root causes instead of patching symptoms.
Debugging is the most under-taught skill in software. Most engineers debug by trial and error; senior engineers debug by hypothesis. This lesson teaches the methodical approach.
If you can't reproduce a bug reliably, you can't be sure you fixed it. Step one is always: what's the minimum sequence of actions that triggers the bug? If the reproduction is flaky, the bug is usually in shared state, timing, or external dependencies (databases, APIs, files).
The TOP of the stack is where the error happened. The BOTTOM is where the program started. Most useful frames are the ones in YOUR code, not in node_modules or framework internals. Look at the line, the variable values (if available), and the call chain. Most stack traces tell you 80% of what you need.
Drop this in .vscode/launch.json. Hit F5. Set breakpoints by clicking left of the line numbers.
{"version": "0.2.0","configurations": [{"type": "node","request": "launch","name": "Debug current file","program": "${file}","runtimeArgs": ["-r", "ts-node/register"],"skipFiles": ["<node_internals>/**"]},{"type": "node","request": "attach","name": "Attach to running app on :9229","port": 9229}]}// For an existing Next.js dev server:// Run with: NODE_OPTIONS='--inspect' npm run dev// Then attach via the second config above. Breakpoints in your code halt the server.
Git bisect: when a bug appeared between commit X (works) and HEAD (broken), `git bisect` narrows it to the single commit that introduced it in log2(n) steps. Code bisect: comment out half the code, see if the bug remains. Repeat on whichever half still breaks. Both are how senior engineers find bugs they don't understand: they don't think harder, they isolate.
Patching the symptom: 'add a null check, the error goes away.' Finding the root cause: 'why was that value null in the first place? Because the API returned a 204 No Content and our parser silently fell through. Fix the parser to throw on 204.' Five whys: ask 'why' five times in a row. The fifth answer is usually the real bug. Symptom-patching multiplies bugs over time; root-causing eliminates them.
Use this for every non-trivial bug.
Reproduce the bug at least twice in a row deliberately
Read the stack trace and identify the exact line
Form a hypothesis: WHY would this line behave this way?
Design a single test that would confirm or deny the hypothesis (a logged value, a breakpoint, a unit test)
Run the test, observe, update the hypothesis
Repeat until the hypothesis is confirmed
Fix the root cause, not the symptom
Add a regression test so the bug can never silently come back
If the root cause exposed a class of bugs, search the codebase for similar patterns
Guessing fixes without forming a hypothesis. Each random change is an experiment with no learning. Trusting console.log forever. The VS Code debugger inspects variables, walks the stack, and changes values inline. Learn it. Skipping the regression test. Without it, the next deploy can silently reintroduce the same bug. Treating 'works on my machine' as a fix. The next environment exposes the missing case. Hiding the bug behind a try/catch. Now you have two bugs, the original and the silent failure.
Pick the highest-leverage diagnostic.
Sign in and purchase access to unlock this lesson.