Documentation
Topics Overview Overview Linux macOS Windows VS Code for the Web Raspberry Pi Network Additional Components Uninstall VS Code Tutorial Copilot Quickstart User Interface Personalize VS Code Install Extensions Tips and Tricks Intro Videos Overview Setup Quickstart Overview Language Models Context Tools Agents Customization Trust & Safety Overview Agents Tutorial Agents Window Planning Memory Tools Subagents Local Agents Copilot CLI Cloud Agents Third-Party Agents Overview Chat Sessions Add Context Inline Chat Review Edits Checkpoints Artifacts Panel Debug Chat Interactions Prompt Examples Overview Instructions Prompt Files Custom Agents Agent Skills Language Models MCP Hooks Plugins Context Engineering Customize AI Test-Driven Development Edit Notebooks with AI Test with AI Test Web Apps with Browser Tools Debug with AI MCP Dev Guide OpenTelemetry Monitoring Inline Suggestions Smart Actions Best Practices Security Troubleshooting FAQ Cheat Sheet Settings Reference MCP Configuration Workspace Context Display Language Layout Keyboard Shortcuts Settings Settings Sync Extension Marketplace Extension Runtime Security Themes Profiles Overview Voice Interactions Command Line Interface Telemetry Basic Editing IntelliSense Code Navigation Refactoring Snippets Overview Multi-Root Workspaces Workspace Trust Tasks Debugging Debug Configuration Testing Port Forwarding Integrated Browser Overview Quickstart Staging & Committing Branches & Worktrees Repositories & Remotes Merge Conflicts Collaborate on GitHub Troubleshooting FAQ Getting Started Tutorial Terminal Basics Terminal Profiles Shell Integration Appearance Advanced Overview Enterprise Policies AI Settings Extensions Telemetry Updates Overview JavaScript JSON HTML Emmet CSS, SCSS and Less TypeScript Markdown PowerShell C++ Java PHP Python Julia R Ruby Rust Go T-SQL C# .NET Swift Working with JavaScript Node.js Tutorial Node.js Debugging Deploy Node.js Apps Browser Debugging Angular Tutorial React Tutorial Vue Tutorial Debugging Recipes Performance Profiling Extensions Tutorial Transpiling Editing Refactoring Debugging Quick Start Tutorial Run Python Code Editing Linting Formatting Debugging Environments Testing Python Interactive Django Tutorial FastAPI Tutorial Flask Tutorial Create Containers Deploy Python Apps Python in the Web Settings Reference Getting Started Navigate and Edit Refactoring Formatting and Linting Project Management Build Tools Run and Debug Testing Spring Boot Modernizing Java Apps Application Servers Deploy Java Apps GUI Applications Extensions FAQ Intro Videos GCC on Linux GCC on Windows GCC on Windows Subsystem for Linux Clang on macOS Microsoft C++ on Windows Build with CMake CMake Tools on Linux CMake Quick Start C++ Dev Tools for Copilot Editing and Navigating Debugging Configure Debugging Refactoring Settings Reference Configure IntelliSense Configure IntelliSense for Cross-Compiling FAQ Intro Videos Get Started Navigate and Edit IntelliCode Refactoring Formatting and Linting Project Management Build Tools Package Management Run and Debug Testing FAQ Overview Node.js Python ASP.NET Core Debug Docker Compose Registries Deploy to Azure Choose a Dev Environment Customize Develop with Kubernetes Tips and Tricks Overview Jupyter Notebooks Data Science Tutorial Python Interactive Data Wrangler Quick Start Data Wrangler PyTorch Support Azure Machine Learning Manage Jupyter Kernels Jupyter Notebooks on the Web Data Science in Microsoft Fabric Foundry Toolkit Overview Foundry Toolkit Copilot Tools Create Agents Models Playground Agent Builder Agent Inspector Evaluation Tool Catalog Fine-Tuning (Automated Setup) Fine-Tuning (Project Template) Model Conversion Tracing Profiling (Windows ML) FAQ File Structure Manual Model Conversion Manual Model Conversion on GPU Setup Environment Without Foundry Toolkit Template Project Migrating from Visualizer to Agent Inspector Overview Getting Started Resources View Deployment VS Code for the Web - Azure Containers Azure Kubernetes Service Kubernetes MongoDB Remote Debugging for Node.js Overview SSH Dev Containers Windows Subsystem for Linux GitHub Codespaces VS Code Server Tunnels SSH Tutorial WSL Tutorial Tips and Tricks FAQ Overview Tutorial Attach to Container Create Dev Container Advanced Containers devcontainer.json Dev Container CLI Tips and Tricks FAQ Default Keyboard Shortcuts Default Settings Substitution Variables Tasks SchemaOn this page there are 17 sections
Node.js debugging in VS Code
The Visual Studio Code editor has built-in debugging support for the Node.js runtime and can debug JavaScript, TypeScript, and many other languages that are transpiled into JavaScript. Setting up a project for Node.js debugging is straightforward with VS Code providing appropriate launch configuration defaults and snippets.
There are a few ways you can debug your Node.js programs in VS Code:
- Use auto attach to debug processes you run in VS Code's integrated terminal.
- Use the JavaScript debug terminal, similar to using the integrated terminal.
- Use a launch config to start your program, or attach to a process launched outside of VS Code.
Auto Attach
If the Auto Attach feature is enabled, the Node debugger automatically attaches to certain Node.js processes that have been launched from VS Code's Integrated Terminal. To enable the feature, either use the Toggle Auto Attach command from the Command Palette (⇧⌘P (Windows, Linux Ctrl+Shift+P)) or, if it's already activated, use the Auto Attach Status bar item.
There are three modes for auto attach, which you can select in the resulting Quick Pick and via the debug.javascript.autoAttachFilter setting:
- smart - If you execute a script outside of your node_modules folder or use a common 'runner' script like mocha or ts-node, the process will be debugged. You can configure the 'runner' script allow list using the Auto Attach Smart Pattern setting (debug.javascript.autoAttachSmartPattern).
- always - All Node.js processes launched in the Integrated Terminal will be debugged.
- onlyWithFlag - Only processes launched with the --inspect or --inspect-brk flag will be debugged.
After enabling Auto Attach, you'll need to restart your terminal by clicking the ⚠ icon in the top right of the terminal, or just creating a new one. Then, the debugger should attach to your program within a second:
When auto attach is on, the Auto Attach item will appear in the status bar across the bottom of the VS Code window. Clicking it allows you to change the auto attach mode, or temporarily turn it off. Temporarily turning off auto attach is useful if you're running some one-off programs where you don't need debugging, but you don't want to disable the feature entirely.
Additional Configuration
Other Launch Configuration Properties
You can apply other properties normally found in launch.json to auto attach in the debug.javascript.terminalOptions setting. For example, to add node internals to your skipFiles, you could add the following to your user or workspace settings:
/**" ] },Auto Attach Smart Patterns
In smart Auto Attach mode, VS Code will try to attach to your code, and not attach to build tools you aren't interested in debugging. It does this by matching the main script against a list of glob patterns. The glob patterns are configurable in the debug.javascript.autoAttachSmartPattern setting, which defaults to:
[ '!**/node_modules/**', '**/$KNOWN_TOOLS$/**', '!**/node_modules/mocha/**', // use "!" to exclude all scripts in "mocha" node modules '**/node_modules/my-cool-test-runner/**' // include scripts in the custom test runner ];JavaScript Debug Terminal
In a similar way to auto attach, the JavaScript Debug Terminal will automatically debug any Node.js process you run in it. You can create a Debug Terminal by running the Debug: Create JavaScript Debug Terminal command from the Command Palette (kbs(workbench.action.showCommands)), or by selecting the Create JavaScript Debug Terminal from the terminal switcher dropdown.
Additional Configuration
Other Launch Configuration Properties
You can apply other properties normally found in launch.json to the debug terminal in the debug.javascript.terminalOptions setting. For example, to add node internals to your skipFiles, you could add the following to your user or workspace settings:
/**" ] },Launch Configuration
Launch configs are the traditional way to set up debugging in VS Code, and provide you the most configuration options for running complex applications.
In this section we'll go into more detail about configurations and features for more advanced debugging scenarios. You'll find instruction for debugging with source maps, stepping over external code, doing remote debugging, and much more.
If you'd like to watch an introductory video, see Getting started with debugging in VS Code.
Note: If you are just getting started with VS Code, you can learn about general debugging features and creating launch.json configuration files in the Debugging topic.
Launch configuration attributes
Debugging configurations are stored in a launch.json file located in your workspace's .vscode folder. An introduction into the creation and use of debugging configuration files is in the general Debugging article.
Below is a reference of common launch.json attributes specific to the Node.js debugger. You can view the complete set of options in the vscode-js-debug options documentation.
The following attributes are supported in launch configurations of type launch and attach:
- outFiles - array of glob patterns for locating generated JavaScript files. See section Source maps.
- resolveSourceMapLocations - an array of glob patterns for locations where source maps should be parsed. See section Source maps.
- timeout - when restarting a session, give up after this number of milliseconds. See section Attaching to Node.js.
- stopOnEntry - break immediately when the program launches.
- localRoot - VS Code's root directory. See section Remote debugging below.
- remoteRoot - Node's root directory. See section Remote debugging below.
- smartStep- try to automatically step over code that doesn't map to source files. See section Smart stepping.
- skipFiles - automatically skip files covered by these glob patterns. See section Skipping uninteresting code.
- trace - enable diagnostic output.
These attributes are only available for launch configurations of request type launch:
- program - an absolute path to the Node.js program to debug.
- args - arguments passed to the program to debug. This attribute is of type array and expects individual arguments as array elements.
- cwd - launch the program to debug in this directory.
- runtimeExecutable - absolute path to the runtime executable to be used. Default is node. See section Launch configuration support for 'npm' and other tools.
- runtimeArgs - optional arguments passed to the runtime executable.
- runtimeVersion - if "nvm" (or "nvm-windows") or "nvs" is used for managing Node.js versions, this attribute can be used to select a specific version of Node.js. See section Multi version support below.
- env - optional environment variables. This attribute expects environment variables as a list of string typed key/value pairs.
- envFile - optional path to a file containing environment variable definitions. See section Load environment variables from external file below.
- console - the console to launch the program (internalConsole, integratedTerminal, externalTerminal). See section Node Console below.
- outputCapture - if set to std, output from the process stdout/stderr will be shown in the Debug Console, instead of listening to output over the debug port. This is useful for programs or log libraries that write directly to the stdout/stderr streams instead of using console.* APIs.
This attribute is only available for launch configurations of request type attach:
- restart - restart the connection on termination. See section Restarting debug session automatically.
- port - debug port to use. See sections Attaching to Node.js and Remote debugging.
- address - TCP/IP address of the debug port. See sections Attaching to Node.js and Remote debugging.
- processId - the debugger tries to attach to this process after having sent a USR1 signal. With this setting, the debugger can attach to an already running process that was not started in debug mode. When using the processId attribute, the debug port is determined automatically based on the Node.js version (and the used protocol) and cannot be configured explicitly. So don't specify a port attribute.
- continueOnAttach - whether to continue the process if it's paused when we attach to it. This option is useful if you launch your program with --inspect-brk.
Launch configurations for common scenarios
You can trigger IntelliSense (⌃Space (Windows, Linux Ctrl+Space)) in your launch.json file to see launch configuration snippets for commonly used Node.js debugging scenarios.
You can also bring up the snippets with the Add Configuration... button in the lower right of the launch.json editor window.
The following snippets are available:
- Launch Program: Launch a Node.js program in debug mode.
- Launch via npm: Launch a Node.js program through an npm 'debug' script. You can use an npm debug script from your launch configuration if it has been defined in your package.json. The debug port used in the npm script must correspond to the port specified in the snippet.
- Attach: Attach to the debug port of a locally running Node.js program. Make sure that the Node.js program to debug has been started in debug mode, and the debug port used is the same as the one specified in the snippet.
- Attach to Remote Program: Attach to the debug port of a Node.js program running on the host specified by the address attribute. Make sure that the Node.js program to debug has been started in debug mode, and the debug port used is the same as the one specified in the snippet. To help VS Code map source files between your workspace and the filesystem of the remote host, make sure to specify correct paths for the localRootand remoteRoot attributes.
- Attach by Process ID: Open the process picker to select a node or gulp process for debugging. With this launch configuration, you can even attach to a node or gulp process that was not started in debug mode.
- Nodemon Setup: Use nodemon to relaunch a debug session automatically whenever the JavaScript source has changed. Make sure that you have nodemon installed globally. Note that terminating the debug session only terminates the program to debug, not nodemon itself. To terminate nodemon, press Ctrl+C in the Integrated Terminal.
- Mocha Tests: Debug mocha tests in a test folder of your project. Make sure that your project has 'mocha' installed in its node_modules folder.
- Yeoman generator: Debug a yeoman generator. The snippet asks you to specify the name of the generator. Make sure that your project has 'yo' installed in its node_modules folder and that your generated project has been installed for debugging by running npm link in the project folder.
- Gulp task: Debug a gulp task. Make sure that your project has 'gulp' installed in its node_modules folder.
- Electron Main: Debug the main Node.js process of an Electron application. The snippet assumes that the Electron executable has been installed inside the node_modules/.bin directory of the workspace.
Node console
By default, Node.js debug sessions launch the target in the internal VS Code Debug Console. Since the Debug Console does not support programs that need to read input from the console, you can enable either an external terminal or use the VS Code Integrated Terminal by setting the console attribute in your launch configuration to externalTerminal or integratedTerminal respectively. The default is internalConsole.
In an external terminal, you can configure which terminal program to use via the terminal.external.windowsExec, terminal.external.osxExec, and terminal.external.linuxExec settings.
Launch configuration support for 'npm' and other tools
Instead of launching the Node.js program directly with node, you can use 'npm' scripts or other task runner tools directly from a launch configuration:
- You can use any program available on the PATH (for example 'npm', 'mocha', 'gulp', etc.) for the runtimeExecutable attribute and arguments can be passed via runtimeArgs.
- You do not have to set the program attribute if your npm script or other tool implicitly specifies the program to launch.
Let's look at an 'npm' example. If your package.json has a 'debug' script, for example:
{ "name": "Launch via npm", "type": "node", "request": "launch", "cwd": "${workspaceFolder}", "runtimeExecutable": "npm", "runtimeArgs": ["run-script", "debug"] }Multi version support
If you are using 'nvm' (or 'nvm-windows') to manage your Node.js versions, it is possible to specify a runtimeVersion attribute in a launch configuration for selecting a specific version of Node.js:
{ "type": "node", "request": "launch", "name": "Launch test", "runtimeVersion": "chackracore/8.9.4/x64", "program": "${workspaceFolder}/test.js" }Make sure to have those Node.js versions installed that you want to use with the runtimeVersion attribute, as the feature will not download and install the version automatically. For example, you'll have to run something like nvm install 7.10.1 or nvs add 7.10.1 from the integrated terminal if you plan to add "runtimeVersion": "7.10.1" to your launch configuration.
If you omit the minor and patch version and have, for example, "runtimeVersion": "14", then the most recent 14.x.y version installed on your system will be used.
Load environment variables from external file
The VS Code Node debugger supports loading environment variables from a file and passing them to the Node.js runtime. To use this feature, add an attribute envFile to your launch configuration and specify the absolute path to the file containing the environment variables:
USER=doe PASSWORD=abc123 # a comment # an empty value: empty= # new lines expanded in quoted strings: lines="foo\nbar"Attaching to Node.js
If you want to attach the VS Code debugger to an external Node.js program, launch Node.js as follows:
node --inspect-brk program.jsOptions to attach the debugger to your program:
- Open a "process picker" that lists all potential candidate processes and let you pick one, or
- Create an "attach" configuration that explicitly specifies all configuration options and then press F5.
Let's go through these options in detail:
Attach to Node Process action
The Attach to Node Process command from the Command Palette (⇧⌘P (Windows, Linux Ctrl+Shift+P)) opens a Quick Pick menu that lists all potential processes that are available to the Node.js debugger:
The individual processes listed in the picker show the debug port and process ID. Once you select your Node.js process in that list, the Node.js debugger will try to attach to it.
In addition to Node.js processes, the picker also shows other programs that were launched with one of the various forms --inspect arguments. This makes it possible to attach to Electron's or VS Code's helper processes.
Setting up an "Attach" configuration
This option requires more work but in contrast to the previous two options it allows you to configure various debug configuration options explicitly.
The simplest "attach" configuration looks like this:
{ "name": "Attach to Process", "type": "node", "request": "attach", "processId": "53426" }To avoid repeatedly entering a new process ID in the launch configuration, Node debug supports a command variable PickProcess that will open the process picker (from above).
Using the PickProcess variable the launch configuration looks like this:
tsc --sourceMap --outDir bin app.tsBabel
For Babel, you'll want to set the sourceMaps option to true, or pass the --source-maps option when compiling your code.
{ "version": "0.2.0", "configurations": [ { "name": "Launch TypeScript", "type": "node", "request": "launch", "program": "app.ts", "outFiles": ["${workspaceFolder}/bin/**/*.js"] } ] }Note that the outFiles should match your JavaScript files, not the source map files (which may end in .map instead of .js).
Source Map Resolution
By default, only source maps in your outFiles will be resolved. This behavior is used to prevent dependencies from interfering with breakpoints you set. For example, if you had a file src/index.ts and a dependency had a source map that referenced webpack:///./src/index.ts, that would incorrectly resolve to your source file and could lead to surprising results.
You can configure this behavior by setting the resolveSourceMapLocations option. If set to null, every source map will be resolved. For example, this configuration will additionally allow source maps in node_modules/some-dependency to be resolved:
{ 'webpack:///./~/*': "${workspaceFolder}/node_modules/*", 'webpack:////*': '/*', 'webpack://@?:*/?:*/*': "${workspaceFolder}/*", // and some more patterns... }This maps paths or URLs in the source map from the left to the right. The pattern ?:* is a non-greedy, non-capturing match, and * is a greedy capturing match. The debugger then replaces the corresponding * in the right-hand pattern with the fragment captured from the source map path. For example, the last pattern in the above example would map webpack://@my/package/foo/bar to ${workspaceFolder}/foo/bar.
Note that for browser debugging, the webRoot is used in place of the workspaceFolder in the default sourceMapPathOverrides.
Remote debugging
Note: VS Code now has universal remote development capabilities. Using the Remote Development extensions, Node.js development in remote scenarios and containers is no different than Node.js development in a local setup. This is the recommended way to remote debug Node.js programs. Check out the Getting started section and Remote tutorials to learn more.
If you are unable to use any of the Remote Development extensions to debug your Node.js program, below is a guide on how to debug a remote Node.js program from your local instance of VS Code.
The Node.js debugger supports remote debugging where you attach to a process running on a different machine, or in a container. Specify a remote host via the address attribute. For example:
{ "type": "node", "request": "attach", "name": "Attach to remote", "address": "TCP/IP address of process to be debugged", "port": 9229, "localRoot": "${workspaceFolder}", "remoteRoot": "C:\\Users\\username\\project\\server" }Access Loaded Scripts
If you need to set a breakpoint in a script that is not part of your workspace and therefore cannot be easily located and opened through normal VS Code file browsing, you can access the loaded scripts via the LOADED SCRIPTS view in the Run and Debug view:
The LOADED SCRIPTS view lets you quickly select the script by typing its name or filter the list when Enable Filter on Type is on.
Scripts are loaded into a read-only editor where you can set breakpoints. These breakpoints are remembered across debug sessions but you only have access to the script content while a debug session is running.
Restarting debug sessions automatically when source is edited
The restart attribute of a launch configuration controls whether the Node.js debugger automatically restarts after the debug session has ended. This feature is useful if you use nodemon to restart Node.js on file changes. Setting the launch configuration attribute restart to true makes the node debugger automatically try to reattach to Node.js after Node.js has terminated.
If you have started your program server.js via nodemon on the command line like this:
{ "name": "Attach to node", "type": "node", "request": "attach", "restart": true, "port": 9229 }Alternatively, you can start your program server.js via nodemon directly with a launch config and attach the VS Code debugger:
"skipFiles": [ "${workspaceFolder}/node_modules/**/*.js", "${workspaceFolder}/lib/**/*.js" ]all code in the node_modules and lib folders in your project will be skipped. The skipFiles also apply to the location shown when calling console.log and similar methods: the first non-skipped location in the stack will be shown beside the output in the Debug Console.
Built-in core modules of Node.js can be referred to by the 'magic name' <node_internals> in a glob patterns. The following example skips all internal modules:
/**/*.js" ]The exact 'skipping' rules are as follows:
- If you step into a skipped file, you won't stop there - you will stop on the next executed line that is not in a skipped file.
- If you have set the option to break on thrown exceptions, then you won't break on exceptions thrown from skipped files unless they bubble up into a non-skipped file.
- If you set a breakpoint in a skipped file, you will stop at that breakpoint, and you will be able to step through it until you step out of it, at which point normal skipping behavior will resume.
- The location of console messages from inside skip files will be shown as the first non-skipped location in the call stack.
Skipped source is shown in a 'dimmed' style in the CALL STACK view:
Hovering over the dimmed entries explains why the stack frame is dimmed.
A context menu item on the call stack, Toggle skipping this file enables you to easily skip a file at runtime without adding it to your launch config. This option only persists for the current debugging session. You can also use it to stop skipping a file that is skipped by the skipFiles option in your launch config.
Note: The legacy protocol debugger supports negative glob patterns, but they must follow a positive pattern: positive patterns add to the set of skipped files, while negative patterns subtract from that set.
In the following (legacy protocol-only) example all but a 'math' module is skipped:
{ "runtimeArgs": ["--preserve-symlinks"] }If your main script is inside a symlinked path, then you will also need to add the "--preserve-symlinks-main" option. This option is only available in Node 10+.
How do I debug ECMAScript modules?
If you use esm or pass --experimental-modules to Node.js in order to use ECMAScript modules, you can pass these options through the runtimeArgs attribute of launch.json:
- "runtimeArgs": ["--experimental-modules"] - Use the experimental ECMAScript modules support in Node v8.5.0+
- "runtimeArgs": ["-r", "esm"] - Use the esm ES module loader (["-r esm"] without a comma won't work)
How can I set NODE_OPTIONS?
The debugger uses the special NODE_OPTIONS environment variable to set up debugging with your application, and overwriting it will prevent debugging from working correctly. Instead of overwriting it, you should append to it instead. For example, a .bashrc file might have something like this: