Developer Tools

Mastering Debugging in VS Code and IntelliJ

Mastering Debugging In VS Code And IntelliJ

Introduction

Debugging is one of the most essential skills in software development. It goes beyond finding bugs: it is about understanding how your program behaves at every step, verifying assumptions, and building confidence in your code. Whether you use VS Code or IntelliJ IDEA, both editors offer advanced debugging features that can dramatically improve your productivity and reduce the time spent chasing elusive bugs.

In this comprehensive guide, you will learn how to master debugging in both tools. You will understand how to configure debuggers, use breakpoints effectively, inspect variables, step through complex logic, and leverage advanced features like conditional breakpoints and remote debugging. By the end, you will have the skills to debug efficiently in any environment.

Why Debugging Matters

Writing code is only half the job; understanding what it does at runtime is equally important. Debugging allows you to stop program execution, inspect variable states, and verify assumptions about your logic in real time.

  • Catch errors early: Find issues during development rather than production
  • Understand complex flows: Step through code to see exactly what happens
  • Verify assumptions: Confirm that variables contain expected values
  • Reduce guesswork: Replace print statements with precise inspection
  • Learn unfamiliar code: Debug to understand how existing code works

Effective debugging saves hours of frustration and leads to more reliable software.

Debugging in VS Code

Visual Studio Code is lightweight but powerful when it comes to debugging. It supports a wide range of languages and frameworks through extensions, making it ideal for full-stack and polyglot developers.

Configuring the Debugger

To start debugging, open your project and click the Run and Debug icon in the sidebar (or press Ctrl+Shift+D). VS Code may automatically detect your environment, but you can configure it manually in .vscode/launch.json.

// .vscode/launch.json - Node.js configuration
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Application",
      "program": "${workspaceFolder}/src/index.js",
      "skipFiles": ["<node_internals>/**"],
      "env": {
        "NODE_ENV": "development"
      }
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Tests",
      "program": "${workspaceFolder}/node_modules/jest/bin/jest",
      "args": ["--runInBand", "--watchAll=false"],
      "console": "integratedTerminal"
    },
    {
      "type": "node",
      "request": "attach",
      "name": "Attach to Process",
      "port": 9229,
      "restart": true
    }
  ]
}
// Python configuration
{
  "type": "python",
  "request": "launch",
  "name": "Debug Python",
  "program": "${file}",
  "console": "integratedTerminal",
  "justMyCode": false  // Debug into library code
}

Using Breakpoints Effectively

Add breakpoints by clicking to the left of a line number or pressing F9. VS Code supports several breakpoint types:

  • Line breakpoints: Pause at a specific line
  • Conditional breakpoints: Pause only when a condition is true (right-click breakpoint)
  • Logpoints: Log a message without pausing (useful for production debugging)
  • Function breakpoints: Pause when entering a specific function
  • Exception breakpoints: Pause when exceptions are thrown
// Conditional breakpoint example:
// Right-click the breakpoint and set condition:
// user.id === 42 && user.role === 'admin'

// Logpoint example (logs without pausing):
// "User {user.name} logged in at {new Date().toISOString()}"

Stepping Through Code

The Debug Toolbar provides controls for navigating through code:

  • Continue (F5): Resume execution until next breakpoint
  • Step Over (F10): Execute current line and move to next
  • Step Into (F11): Enter function calls on current line
  • Step Out (Shift+F11): Finish current function and return to caller
  • Restart (Ctrl+Shift+F5): Restart debugging session
  • Stop (Shift+F5): End debugging session

Inspecting Variables and State

The Debug sidebar shows several panels for inspection:

  • Variables: Local, closure, and global variables with current values
  • Watch: Custom expressions you want to monitor
  • Call Stack: Function calls that led to current position
  • Breakpoints: All breakpoints in the project

The Debug Console allows you to evaluate expressions in the current context:

// In Debug Console, you can:
user.permissions.filter(p => p.active)
JSON.stringify(response.data, null, 2)
this.calculateTotal(items)

Debugging Extensions for VS Code

  • Debugger for Chrome/Edge: Debug web applications in the browser
  • Python Extension: Full-featured debugging for Python projects
  • Docker Extension: Attach debuggers to containers
  • Remote Development: Debug code on servers, containers, or WSL
  • Live Share: Collaborative debugging with teammates

Debugging in IntelliJ IDEA

IntelliJ IDEA is known for its deep integration with JVM languages like Java, Kotlin, and Scala. It provides advanced debugging features out of the box that enterprise developers rely on for complex applications.

Starting a Debug Session

Click beside line numbers to set breakpoints, then run in Debug mode using the bug icon or Shift+F9. IntelliJ opens the Debugger Tool Window automatically when hitting a breakpoint.

Breakpoint Configuration

IntelliJ provides extensive breakpoint options (right-click any breakpoint):

// Conditional breakpoint
Condition: user.getRole().equals("ADMIN") && user.getAge() > 18

// Log expression (does not suspend)
Evaluate and log: "Processing user: " + user.getName()

// Hit count - break after N hits
Pass count: 100

// Instance filter - break only for specific object instances
Instance filters: myService@1234
  • Exception breakpoints: Pause when specific exceptions are thrown
  • Field watchpoints: Pause when a field is read or modified
  • Method breakpoints: Pause on method entry or exit

Evaluate Expression

The Evaluate Expression feature (Alt+F8) lets you test code snippets in the current context:

// Evaluate arbitrary expressions
userRepository.findById(userId)
Stream.of(items).filter(Item::isActive).count()
new ObjectMapper().writeValueAsString(response)

This is powerful for testing fixes without restarting the application.

Advanced IntelliJ Debugging Features

  • Smart Step Into: When a line has multiple method calls, choose which to step into
  • Drop Frame: Return to a previous point in the call stack (undo execution)
  • Force Return: Exit a method early with a specified return value
  • HotSwap: Update code during debugging without restarting (JVM)
  • Memory View: Visualize object references and track memory usage
  • Stream Debugger: Visualize Java Stream operations step by step
// Stream Debugger shows each operation:
List<String> result = users.stream()
    .filter(u -> u.isActive())      // See filtered elements
    .map(User::getName)              // See mapped values
    .sorted()                        // See sorted order
    .collect(Collectors.toList());   // See final result

Remote Debugging

Both VS Code and IntelliJ support remote debugging for applications running on servers or in containers.

# Start Java application with debug agent
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -jar app.jar

# Start Node.js with inspector
node --inspect=0.0.0.0:9229 app.js

Then create an attach configuration in your IDE to connect to the remote process.

VS Code vs IntelliJ: Which Is Better for Debugging

Feature VS Code IntelliJ IDEA
Language Support Broad via extensions Deep for JVM, good for JS/Python
Performance Lightweight and fast Heavier but more integrated
Configuration JSON-based, flexible GUI-based, discoverable
Advanced Features Requires extensions Built-in (HotSwap, Stream Debugger)
Remote Debugging Excellent with extensions Excellent built-in
Best For Full-stack, web, polyglot Backend, enterprise, JVM

Choose based on your primary stack. Many developers use both: IntelliJ for backend Java/Kotlin work and VS Code for frontend and scripting.

Debugging Best Practices

Use Conditional Breakpoints

Instead of stepping through hundreds of loop iterations, set a condition that triggers only on the problematic case.

Combine Logging and Debugging

Use logpoints for ongoing monitoring and breakpoints for deep investigation. They complement each other.

Debug Before Changing Code

Understand exactly what is happening before modifying anything. Many bugs are misdiagnosed because developers change code based on assumptions.

Use Watch Expressions

Track critical values across stepping operations. Watch expressions update automatically as you navigate through code.

Learn Keyboard Shortcuts

Debugging is much faster when you can step through code without reaching for the mouse. Memorize F5, F10, F11, and your IDE’s evaluate shortcut.

When to Use Which Tool

Choose VS Code When

  • Working with JavaScript, TypeScript, or Python
  • Building web applications or APIs
  • Need a lightweight, fast editor
  • Working across multiple languages in one session
  • Debugging in containers or remote environments

Choose IntelliJ When

  • Working primarily with Java, Kotlin, or Scala
  • Need advanced features like HotSwap or Stream Debugger
  • Building enterprise applications
  • Want integrated refactoring and debugging
  • Working with complex frameworks like Spring

Conclusion

Mastering debugging in VS Code and IntelliJ is about understanding how each tool fits your workflow and using its features effectively. VS Code shines in speed, flexibility, and cross-language support, while IntelliJ excels in deep, structured debugging of complex JVM applications. Both provide the core capabilities you need: breakpoints, variable inspection, stepping controls, and expression evaluation. The key is learning to use these features fluently rather than falling back on print statements.

To enhance your VS Code setup further, read Top VS Code Extensions for Full-Stack Developers (2025 Edition). For understanding testing strategies that complement debugging, see Unit Testing in JavaScript with Jest and Vitest. For debugging mobile applications, explore Debugging & Profiling React Native Apps with Flipper. Reference the official VS Code debugging documentation and the IntelliJ debugging documentation for the latest features and techniques.

Leave a Comment