Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Node.js Dictionary
  3. debug

debug

Node.js offers multiple debugging approaches. This page covers everything from quick console.log debugging to graphical debuggers using the --inspect flag with Chrome DevTools or VSCode, as well as the debug module for conditional log output.

Debugging Method Comparison

MethodDescriptionBest For
console.logOutputs values to the terminal. The simplest approach.Quick value checks, tracing execution flow.
node --inspectConnects to Chrome DevTools for breakpoint-based debugging.Variable monitoring, call stack inspection.
VSCode DebuggerSet breakpoints in the editor and step through code.Full-scale development, code step execution.
debug moduleOutputs logs conditionally per namespace. Safe design that does not leak into production.Library and module-specific debug logs.
console.trace()Outputs the call stack trace of the caller.Finding out which code called a function.
console.time()Measures execution time.Quick performance measurement.

console.log Debugging

console.log() is the foundation of debugging. console.error() writes to stderr, allowing logs and errors to be handled separately. console.dir() expands and displays even deeply nested objects.

console_debug.js
// Basic output
var fighter = { name: 'Son Goku', power: 'Kamehameha', level: 9000 };
console.log('Fighter data:', fighter);

// console.error writes to stderr
console.error('[ERROR] Damage calculation failed');

// console.dir shows object details
var nested = { team: { name: 'Earthlings', members: ['Son Goku', 'Vegeta', 'Piccolo'] } };
console.dir(nested, { depth: null }); // depth: null expands all levels

// console.table displays arrays and objects in table format
var fighters = [
    { name: 'Son Goku', power: 'Kamehameha',   level: 9000  },
    { name: 'Vegeta',   power: 'Galick Gun',   level: 8000  },
    { name: 'Frieza',   power: 'Death Beam',   level: 10000 },
];
console.table(fighters);

// Measure execution time
console.time('battle time');
var sum = 0;
for (var i = 0; i < 1000000; i++) {
    sum += i;
}
console.timeEnd('battle time'); // battle time: X.XXXms

// Output a stack trace
function transform() {
    console.trace('Stack trace');
}
transform();
node console_debug.js
Fighter data: { name: 'Son Goku', power: 'Kamehameha', level: 9000 }
[ERROR] Damage calculation failed
{ team: { name: 'Earthlings', members: [ 'Son Goku', 'Vegeta', 'Piccolo' ] } }
┌─────────┬───────────┬──────────────┬───────┐
│ (index) │ name      │ power        │ level │
├─────────┼───────────┼──────────────┼───────┤
│    0    │ 'Son Goku'│'Kamehameha'  │ 9000  │
│    1    │ 'Vegeta'  │'Galick Gun'  │ 8000  │
│    2    │ 'Frieza'  │'Death Beam'  │ 10000 │
└─────────┴───────────┴──────────────┴───────┘
battle time: 2.541ms
Trace: Stack trace
    at transform (console_debug.js:27:13)
    at Object.<anonymous> (console_debug.js:30:1)

node --inspect and Chrome DevTools

Launching with the node --inspect flag lets you connect Chrome DevTools to the Node.js process, enabling breakpoint stops, variable monitoring, and call stack inspection.

inspect_sample.js
// Script to debug
var fighters = [
    { name: 'Son Goku', power: 9000  },
    { name: 'Vegeta',   power: 8000  },
    { name: 'Frieza',   power: 10000 },
    { name: 'Piccolo',  power: 3500  },
];

function findStrongest(list) {
    var strongest = list[0];
    for (var i = 1; i < list.length; i++) {
        // Set a breakpoint here to watch how strongest changes
        if (list[i].power > strongest.power) {
            strongest = list[i];
        }
    }
    return strongest;
}

var result = findStrongest(fighters);
console.log('Strongest:', result.name, 'Power:', result.power);

Follow these steps to debug.

node --inspect inspect_sample.js
Debugger listening on ws://127.0.0.1:9229/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
For help, see: https://nodejs.org/en/docs/inspector

Enter chrome://inspect in the Chrome address bar. The Node.js process appears under "Remote Target". Click "inspect" to open DevTools, where you can set breakpoints in the "Sources" tab.

To stop immediately when the script starts, use --inspect-brk.

node --inspect-brk inspect_sample.js
Debugger listening on ws://127.0.0.1:9229/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

VSCode Debugger Configuration

VSCode has a built-in Node.js debugger. Create .vscode/launch.json to configure it. Click the gutter (left of line numbers) to set breakpoints, and press F5 to start debugging.

.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Run",
      "skipFiles": ["<node_internals>/**"],
      "program": "${workspaceFolder}/inspect_sample.js"
    },
    {
      "type": "node",
      "request": "attach",
      "name": "Attach to Running Process",
      "port": 9229
    }
  ]
}

The operations after configuration are as follows.

KeyDescription
F5Start the debug session.
F9Toggle a breakpoint on the current line.
F10Step over (advance to next line without entering the function).
F11Step into (enter the function).
Shift+F11Step out (exit the current function).
F5 (while paused)Resume execution to the next breakpoint.

Using the debug Module

The debug module is a debugging utility distributed via npm. It creates loggers with namespaces and uses the environment variable DEBUG to control which namespaces are enabled. Unlike console.log, nothing is output in production unless the environment variable is set.

npm install debug
debug_module.js
var createDebug = require('debug');

// Create a debugger per namespace
var debugBattle = createDebug('dragonball:battle');
var debugPower  = createDebug('dragonball:power');
var debugApp    = createDebug('dragonball:app');

var fighters = [
    { name: 'Son Goku', power: 9000 },
    { name: 'Vegeta',   power: 8000 },
    { name: 'Trunks',   power: 7500 },
];

function battle(attacker, defender) {
    debugBattle('Battle start: %s vs %s', attacker.name, defender.name);
    debugPower('Attacker power: %d', attacker.power);
    debugPower('Defender power: %d', defender.power);

    if (attacker.power > defender.power) {
        debugBattle('%s wins!', attacker.name);
        return attacker;
    } else {
        debugBattle('%s wins!', defender.name);
        return defender;
    }
}

debugApp('Application started');
var winner = battle(fighters[0], fighters[1]);
console.log('Winner:', winner.name);

Specify the namespace to enable using the DEBUG environment variable when running.

DEBUG=dragonball:battle node debug_module.js
  dragonball:battle Battle start: Son Goku vs Vegeta +0ms
  dragonball:battle Son Goku wins! +1ms
Winner: Son Goku
DEBUG=dragonball:* node debug_module.js
  dragonball:app Application started +0ms
  dragonball:battle Battle start: Son Goku vs Vegeta +1ms
  dragonball:power Attacker power: 9000 +0ms
  dragonball:power Defender power: 8000 +0ms
  dragonball:battle Son Goku wins! +0ms
Winner: Son Goku
node debug_module.js
Winner: Son Goku

Nothing is output when the DEBUG environment variable is not set. Use DEBUG=* to enable all namespaces. Multiple namespaces can be specified separated by commas (e.g., DEBUG=dragonball:battle,dragonball:power).

Summary

console.log() is convenient, but leaving too many in the code makes it messy, requiring eventual cleanup. Using the debug module allows environment variable control, so development logs do not carry over to production.

For serious debugging, node --inspect with Chrome DevTools or VSCode's built-in debugger is effective. Being able to stop execution at a breakpoint and inspect variables is a more efficient way to identify bugs than writing a large number of console.log statements.

Including the VSCode configuration file .vscode/launch.json in the repository allows all team members to start debugging with the same settings.

Common Mistakes

Common Mistake 1: Forgetting to Set the DEBUG Environment Variable

The debug module produces no output if the DEBUG environment variable is not set. When logs do not appear, it is tempting to think the code is wrong, but the cause is often a missing DEBUG setting.

Incorrect example (running without setting DEBUG):

var createDebug = require('debug');
var debug = createDebug('dragonball:battle');

debug('Battle start: Son Goku vs Vegeta');
node app.js

Nothing is output. The correct way to run is as follows.

DEBUG=dragonball:* node app.js
  dragonball:battle Battle start: Son Goku vs Vegeta +0ms

Common Mistake 2: Setting DEBUG=* in Production

Setting DEBUG=* in production causes all namespace debug logs to be output. Internal processing flows and configuration values become visible externally, and heavy log output degrades performance. In production, either do not set the DEBUG environment variable, or explicitly specify only the needed namespaces.

Incorrect example (production configuration file):

# .env.production (incorrect pattern)
DEBUG=*
NODE_ENV=production
PORT=8080

Correct approach (do not set DEBUG in production):

# .env.production
NODE_ENV=production
PORT=8080

Common Mistake 3: Inconsistent Namespace Naming Conventions

Standardizing namespaces in the format appname:modulename allows filtering with DEBUG=dragonball:*. Inconsistent naming makes it difficult to enable logs for specific modules only.

Incorrect example (inconsistent naming):

var createDebug = require('debug');

// Inconsistent naming
var d1 = createDebug('battle');           // No app name
var d2 = createDebug('dragonball-power'); // Hyphen separator
var d3 = createDebug('DB');              // Uppercase abbreviation

Correct approach (standardize on appname:modulename format):

var createDebug = require('debug');

// Standardize on appname:modulename
var debugBattle = createDebug('dragonball:battle');
var debugPower  = createDebug('dragonball:power');
var debugDb     = createDebug('dragonball:db');

// All can be enabled at once with DEBUG=dragonball:*

If you find any errors or copyright issues, please .