{"post":{"slug":"how-to-use-a-debugger-2026","title":"How to use a debugger in 2026: stop printing and start stepping","excerpt":"Most developers reach for print statements when a debugger would solve the same problem in a quarter of the time. This 2026 guide covers every essential technique.","category":"code","date":"March 17, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">T</span>he debugger is the most underused tool in most developers' arsenal. A survey of engineering teams in 2025 found that over 60% of respondents reach for `console.log` or `print` before a debugger, even for complex multi-step bugs. The reason is familiarity, not effectiveness. A debugger gives you a live snapshot of the entire program state at the moment you care about — a print gives you whatever you thought to print before you knew what was wrong.\n\n## What changed in 2026\n\n- **VS Code debugger is now first-class for most languages.** Node, Python, Go, Rust, Java, C++ — all work out of the box with minimal configuration. The days of \"it's too hard to set up\" are largely over.\n- **Time-travel debugging is production-ready.** Tools like `rr` (Linux), Replay.io (browser), and WinDbg's time-travel on Windows let you step backwards through execution — invaluable for heisenbug and race-condition debugging.\n- **AI-assisted debugging landed in IDEs.** Copilot and Cursor can explain the current state at a breakpoint in natural language. Useful as a second opinion but not a replacement for understanding.\n- **Remote debugging over SSH is standard.** VS Code Remote and JetBrains Gateway make attaching to a debugger on a remote server or container as easy as local debugging.\n\n## Core concepts\n\n### Breakpoint types\n\n| Type | What it does | When to use |\n| --- | --- | --- |\n| Line breakpoint | Pause execution at this line | Starting point for any bug |\n| Conditional breakpoint | Pause only when a condition is true | Loops or repeated calls with specific inputs |\n| Exception breakpoint | Pause when an exception is thrown | Catching errors before they propagate |\n| Logpoint | Log a value without stopping | Low-intrusiveness observation in tight loops |\n| Hit-count breakpoint | Pause after N hits | Finding the 100th iteration of a loop |\n\n### Stepping commands\n\n- **Step Over (F10)** — Execute the current line and stop on the next one. Does not enter called functions.\n- **Step Into (F11)** — Execute the current line AND enter any function called on that line.\n- **Step Out (Shift+F11)** — Finish the current function and pause back in the caller.\n- **Continue (F5)** — Resume until the next breakpoint.\n\nUse Step Over to survey; use Step Into when you suspect the bug is inside a specific function.\n\n## Debugger setup: the essentials\n\n### Node.js / TypeScript in VS Code\n\n```json\n// .vscode/launch.json\n{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Debug API\",\n      \"program\": \"${workspaceFolder}/src/server.ts\",\n      \"runtimeArgs\": [\"--loader\", \"ts-node/esm\"],\n      \"sourceMaps\": true,\n      \"skipFiles\": [\"<node_internals>/**\"]\n    }\n  ]\n}\n```\n\nFor an already-running process, use `--inspect` and attach:\n\n```bash\nnode --inspect src/server.js   # or --inspect-brk to pause at start\n# Then Attach in VS Code or open chrome://inspect\n```\n\n### Python with pdb / VS Code\n\n```python\n# Quick in-code breakpoint (Python 3.7+)\nbreakpoint()  # drops into pdb at runtime\n\n# Or set in VS Code by clicking the gutter — no code change needed\n```\n\n```bash\n# Run with pdb from the terminal\npython -m pdb myscript.py\n# Commands: n (next), s (step), c (continue), p varname, l (list), q (quit)\n```\n\n### Java / JVM in IntelliJ\n\nSet a breakpoint by clicking the gutter. Use \"Evaluate Expression\" (Alt+F8) to run arbitrary code at a breakpoint — this is equivalent to a print without modifying the source.\n\n## Working with the debugger: a workflow\n\n1. **Reproduce the bug deterministically** — a bug you cannot trigger reliably is very hard to debug with or without a debugger.\n2. **Set a breakpoint at the highest-level point you own** — just before the operation you suspect.\n3. **Check the call stack** — understand how you arrived here.\n4. **Inspect variables in scope** — look for nulls, wrong types, unexpected values.\n5. **Step towards the error** — Step Over until behaviour diverges from expectation, then Step Into that call.\n6. **Use conditional breakpoints** if the bug only appears for specific inputs.\n\n```javascript\n// Example: only break when the order is for a large amount\n// Condition: order.total > 10000 && order.currency === 'USD'\n```\n\n## The Watch panel\n\nAdd expressions to the Watch panel to track them as you step:\n\n- Variable: `user.profile.emailVerified`\n- Expression: `items.filter(i => i.status === 'pending').length`\n- Function call: `formatCurrency(rawAmount)` (safe for pure functions)\n\nThis gives you a live dashboard without a single print statement.\n\n## Debugging async code\n\nAsync code is where the debugger earns its keep most decisively.\n\n```typescript\nasync function processPayment(orderId: string) {\n  const order = await fetchOrder(orderId);    // breakpoint here\n  const result = await chargeCard(order);      // then here\n  await updateOrderStatus(orderId, result);    // then here\n}\n```\n\nSet breakpoints inside the async function. The debugger pauses at each `await` in the expected order — something print statements cannot do cleanly across async boundaries.\n\nFor Node.js, enable \"Just My Code\" (`skipFiles`) to hide `node_internals` frames and focus on your own async chain.\n\n## Common mistakes\n\n**Setting breakpoints too deep.** Start one level above where you think the bug is. You can always Step Into.\n\n**Ignoring the call stack panel.** The call stack shows every active frame. Click a frame to inspect its local variables — this is often faster than stepping back to find where a bad value originated.\n\n**Not using conditional breakpoints in loops.** A breakpoint inside a loop that runs 10,000 times will pause 10,000 times. Add a condition.\n\n**Leaving breakpoints in committed code.** `breakpoint()` in Python or a `debugger;` statement in JavaScript will halt production if deployed. Lint rules can catch these: add `no-debugger` to ESLint and equivalent in ruff.\n\n## What to skip\n\n- **Print-driven debugging for async, multi-threaded, or time-sensitive code.** The debugger is the right tool here.\n- **Remote debugging on production** unless you have a read-only replica and strict access controls. Debug on staging.\n- **Debugging without a reproducible test case.** Before attaching the debugger, write a failing test. The test documents the bug and becomes your regression guard.\n\n## FAQ\n\n**Is it worth learning the terminal debugger (pdb, gdb) if I have a GUI?**\nYes, especially for server environments. When you are SSH-ed into a prod-like environment with no GUI, `pdb` or `gdb` is the only option.\n\n**Does the debugger work in Docker containers?**\nYes. Expose the debug port in your `docker-compose.yml` and attach from VS Code Remote or your IDE. Most frameworks have a \"debug mode\" environment variable that enables the inspect port.\n\n**Can I debug a running process I did not start?**\nYes — attach-to-process mode. In VS Code, use \"Attach to Node Process.\" In Python, use `pyrasite` or `debugpy`'s attach mode. In Java, start the JVM with `-agentlib:jdwp`.\n\n**What about debugging in production?**\nDistributed tracing (OpenTelemetry) and structured logging are your debugger in production. Avoid interactive debuggers in prod; use observability instead.\n\n## Where to go next\n\n- [How to read a stack trace in 2026](/blog/how-to-read-a-stack-trace-2026)\n- [How to handle errors gracefully in 2026](/blog/how-to-handle-errors-gracefully-2026)\n- [How to profile slow code in 2026](/blog/how-to-profile-slow-code-2026)","hue":308,"metaTitle":"How to Use a Debugger in 2026: Practical Debugging Guide","metaDescription":"2026 guide to using debuggers in VS Code, IntelliJ, Chrome DevTools, and the terminal. Breakpoints, stepping, watch expressions","keywords":["how to use a debugger 2026","debugging techniques 2026","vs code debugger tutorial","conditional breakpoints","step over step into debugger","javascript debugger 2026","python debugger pdb","chrome devtools debugger","debugger vs print statements","software debugging guide 2026"],"tldr":["**Breakpoints beat print statements** — a breakpoint gives you every variable at the moment of interest; a print gives you one.","**Conditional breakpoints eliminate noise** — break only when `userId == 42` or `retryCount > 3`.","**Step Over vs Step Into matters** — Step Over runs the next line; Step Into enters the function being called.","**Watch expressions and the call stack are your primary tools** — open them first, not last.","**Skip:** \"print-driven development\" for anything involving async, multi-threaded, or time-sensitive code — debuggers win decisively there."],"readTime":"5 min read","wordCount":1168},"related":[{"slug":"how-to-debug-javascript-2026","title":"How to Debug JavaScript in 2026: A Practical Guide","excerpt":"Debugging JavaScript is a method, not a guessing game: read the error, find where it breaks, and test one change at a time. Here is the full workflow.","category":"code","date":"June 5, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":240},{"slug":"how-to-debug-faster-2026","title":"How to debug faster in 2026: a practical method that scales","excerpt":"Most debugging time is wasted guessing. This guide gives you a repeatable method, modern tooling, and the habits that actually cut time-to-fix.","category":"code","date":"June 5, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":205},{"slug":"how-to-debug-code-2026","title":"How to debug code in 2026: a systematic method that actually works","excerpt":"Debugging is the skill that separates productive developers from frustrated ones. Here is the systematic approach that works in 2026, with or without AI.","category":"code","date":"April 15, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":320}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"how-to-upgrade-to-an-ssd-2026","title":"How to upgrade to an SSD in 2026: clone your drive and transform your PC","excerpt":"Swapping a hard drive for an SSD is still the single best upgrade for an older PC or laptop. Here is how to pick the right drive, clone everything, and swap it safely.","category":"tech","date":"March 17, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":242},"older":{"slug":"how-to-use-ai-for-ad-copy-2026","title":"How to use AI for ad copy in 2026: faster testing, better conversion","excerpt":"AI ad copy generation in 2026 is a genuine force multiplier for testing — producing variant volume no human team can match — but it still needs brand voice discipline and conversion data to improve.","category":"ai","date":"March 17, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":202}}