Node.js can expose a running process to a debugger through the V8 Inspector protocol. Use the inspector when a runtime bug needs breakpoints, startup tracing, or variable inspection instead of only log output.

The inspector listener is a local TCP endpoint, and Node.js listens on 127.0.0.1:9229 by default. Keeping the listener on loopback lets local debugger clients attach without opening the debug port to other machines.

The built-in node inspect client keeps the attach path reproducible from a terminal. Chrome DevTools, Edge DevTools, Visual Studio Code, and other inspector clients can attach to the same host and port after the process is started with the inspector enabled.

Steps to debug a Node.js process with the inspector:

  1. Keep the inspector address on loopback unless remote access is protected by a tunnel or firewall.

    Do not bind the inspector to 0.0.0.0 on an untrusted network. A client that reaches the inspector can run code inside the Node.js process.

  2. Start the target script with the inspector paused before user code.
    $ node --inspect-brk=127.0.0.1:9229 server.mjs
    Debugger listening on ws://127.0.0.1:9229/4d8a7b3e-9b22-4b2d-9f3d-6c41d2a8e717
    For help, see: https://nodejs.org/learn/getting-started/debugging

    Replace server.mjs with the application entry point. Use --inspect instead of --inspect-brk when the process should start immediately instead of stopping before user code.

  3. Attach the built-in CLI debugger from a second terminal.
    $ node inspect 127.0.0.1:9229
    connecting to 127.0.0.1:9229 ... ok
    debug> Break on start in server.mjs:1
    > 1 import http from "node:http";
      2 
      3 const server = http.createServer((request, response) => {
    debug>
  4. Set a breakpoint on the line to investigate from the debugger prompt.
    debug> sb(4)
      1 import http from "node:http";
      2 
      3 const server = http.createServer((request, response) => {
    > 4   response.end("debug-ready\n");
      5 });
      6 
      7 server.listen(3000, "127.0.0.1");
      8 

    The 4 is a line number in the paused file, here the line that answers each request.

  5. Continue the paused process so the server starts listening.
    debug> cont
  6. Send a request from a third terminal to reach the breakpoint.
    $ curl --silent http://127.0.0.1:3000/

    The curl command waits without output while the breakpoint holds the request. Use the application's normal smoke test when the process is not an HTTP server or listens on a different local port.

  7. Read a variable at the paused line from the debugger prompt.
    break in server.mjs:4
      2 
      3 const server = http.createServer((request, response) => {
    > 4   response.end("debug-ready\n");
      5 });
      6 
    debug> exec request.url
    '/'

    The node inspect prompt also accepts debugger commands such as next, step, out, and repl after execution reaches code that needs inspection.

  8. Resume the held request from the debugger prompt.
    debug> cont
  9. Confirm the waiting request finishes in the third terminal.
    $ curl --silent http://127.0.0.1:3000/
    debug-ready
Share this guide