126

I was previously using gulp and running gulp to start my application and listeners from the Visual Studio Code debugger but have recently needed to switch to running scripts through npm instead. Unfortunately in VSCode I've not been able to run npm scripts through the debugger so I've had to resort to running node to start my server directly which gets rid of my listener tasks which reloaded code automatically.

This seems like something that should be simple but so far I haven't had much luck. Below is a snippet from my launch.json file that I attempted to use but npm could not be located.

{
    ...
        "program": "npm",
        "args": [
            "run",
            "debug"
        ],
    ...
}

This gives me the following error.

Error request 'launch': program 'c:\myproject\npm' does not exist

Related resources:

Jost
  • 199
  • 1
  • 3
  • 16
jpierson
  • 16,435
  • 14
  • 105
  • 149

13 Answers13

111

It appears that VS Code will support npm scripts and other launch scenarios since the release from October 2016.

Below is an example as it was proposed on GitHub but has been adjusted to use --inspect-brk instead of the originally prposed --debug-brk option.

packages.json

  "scripts": {
    "debug": "node --nolazy --inspect-brk=5858 myProgram.js"
  },

vscode launch config

{
    "name": "Launch via NPM",
    "type": "node",
    "request": "launch",
    "cwd": "${workspaceRoot}",
    "runtimeExecutable": "npm",
    "runtimeArgs": [
        "run-script", "debug"
    ],
    "port": 5858
}

More recent updates for Visual Studio Code as of Summer of 2022 show that there are various ways to set up debugging support with Node.js. These methods include auto attaching to either processes started from the VSCode Integrated Terminal or the JavaScript debug terminal, or by using the traditional launch config which is now extensively documented.

jpierson
  • 16,435
  • 14
  • 105
  • 149
  • 7
    I'm getting "Cannot launch debug target (spawn npm ENOENT)." for the above, on VSCode 1.7.2 – andreister Dec 13 '16 at 20:46
  • 12
    @andreister On Windows, I got it working by using "npm.cmd" instead of simply "npm"! – electrotype Dec 15 '16 at 20:19
  • 1
    I'm wondering about cases where you have a script such as: "grunt test". What then? if you don't launch node manually. – jpierson Aug 24 '17 at 20:53
  • As of Sept 2017 and Node >= 8.4: If debug seems to start but also seems to hang right away, remove the "port" line. No (longer?) needed. Also, add `"protocol": "inspector"` to reduce noise about which inspector gets used... – Frank N Sep 25 '17 at 12:47
  • 1
    @jpierson The default value for "runtimeExecutable" is "node" (according to hover-info in vsode, so probablay an all platforms the respective node executable). If you want to start `anything.js`, put it in program, not runtimeExecutable: `"program": "${workspaceRoot}/your-path/here/anything.js"` (your path here could also be the `node_modules/.bin/whatever` binary of an installed package) – Frank N Sep 25 '17 at 12:49
  • 2
    works for me once I use exactly as the answer but `--inspect-brk=5858` instead of `--debug-brk=5858`. before i changed that it just hung without any deprecation error message. – James Jan 13 '19 at 14:10
  • 2
    I tried with the node flag --inspect-brk and it worked like a charm! – sidd Apr 10 '19 at 07:01
  • "run-script", "debug" works to me because i have the "fast-test" to debbug with mocha with ts using .mocharc-transpile-only.json . So I only need to put "run-script", "fast-test" and it works good. Oh thank you so much bro :) – Richard Rebeco Nov 25 '22 at 15:05
71

VS Code now gives you a "Debug Script" button when you hover over the name of a script in package.json.

enter image description here

Kyle Delaney
  • 11,616
  • 6
  • 39
  • 66
  • If this fails for anyone with an error suggesting setting `outFiles`, you can configure that in your "settings.json" file with `"debug.javascript.terminalOptions": {"outFiles": []}`. More info here: https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_additional-configuration – JohnnyFun Nov 11 '21 at 20:44
  • 15
    How to configure this in launch json? – Jose Manuel Sánchez Jun 08 '22 at 09:33
  • I just get a hover that says "_Run by the 'npm test' command._" – ruffin Jul 02 '22 at 03:20
  • @ruffin You have to hover over the script name (key), not the command string (value). – 1j01 Aug 29 '22 at 23:28
  • https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_auto-attach – Smart Coder Apr 28 '23 at 20:28
43

I think what you're looking for is the following configurations.

Add the following object to the configurations array in .vscode/launch.json file.

{
    "command": "npm run dev",
    "name": "Run npm dev",
    "request": "launch",
    "type": "node-terminal"
}

And try debugging with the new configuration now. VSCode will take care of the debugger attachment.

Don't forget to replace npm run dev with your desired command.

Saleh Mahmood
  • 1,823
  • 1
  • 22
  • 30
  • 6
    it says "Property command is not allowed." – suchcodemuchwow May 04 '21 at 22:57
  • Might want to add "skipFiles": ["/**"] in there as well – Andreas Bergström Jul 01 '22 at 08:59
  • Works in 2023 :)) for typescript project too ``` { "version": "0.2.0", "configurations": [ { "skipFiles": [ "/**" ], "preLaunchTask": "tsc: build - tsconfig.json", "outFiles": [ "${workspaceFolder}/dist/**/*.js" ], "command": "npm run cli:prod x-x:foo:x", "name": "Run npm dev", "request": "launch", "type": "node-terminal" } ] } ``` – AmiNadimi Jan 09 '23 at 06:35
  • This works! And strangely enough I can't find any mention of type = `node-terminal`in the VS Code docs. – Niels Bom May 23 '23 at 11:13
26

I just noticed "JavaScript Debug Terminal" in the "New Terminal" dropdown. VSCode automatically attaches to anything you run in that terminal window.

enter image description here

No more complicated debug configs!

Jack Steam
  • 4,500
  • 1
  • 24
  • 39
  • 8
    This should be marked as the accepted answer. It does not force to change anything code level, which is very critical for large organization projects. – Alexis May 12 '22 at 08:43
  • @Alexis, what about running from F5 or the task launchers. Does it automatically attach to those too without any customization? If so I'd say it's the accepted answer all the way around otherwise having both methods describe I think would be the best. – jpierson Aug 02 '22 at 16:21
24
  1. Configure a new debug target in your .vscode/launch.json:

    {
        "name": "Attach To npm",
        "type": "node",
        "request": "attach",
        "port": 5858,
        "address": "localhost",
        "restart": false,
        "sourceMaps": false,
        "outDir": null,
        "localRoot": "${workspaceRoot}",
        "remoteRoot": null
    }
    
  2. Config your npm to run the node with --debug-brk option:

    "scripts": {
      "start": "node app.js",
      "debug": "node --debug-brk app.js"
      ...
    
  3. Start your app from the shell as:

     $npm run debug
    
  4. The program by default will be waiting in the port 5858 to attach the debugger

  5. So, run the debugger in your visual studio code ("Attach To npm").

  6. Enjoy your debugger :)

Bastien
  • 635
  • 5
  • 16
GutiMac
  • 2,402
  • 1
  • 20
  • 27
  • 7
    Nowadays the node flag is --inspect-brk, and the default port is 9229, at least on my machine. – kaba Feb 16 '18 at 15:08
23

It is feasible with npm whithout having to alter your scripts section in package.json

The trick here is to pass the --inspect-brk=9229 to node.

The command will look like npm run start -- --inspect-brk=9229

Here's the .vscode/launch.json:

{  
"version": "0.2.0",
"configurations": [
    {
        "type": "node",
        "request": "launch",
        "name": "Launch via NPM",
        "runtimeExecutable": "${env:NVM_BIN}/npm", //change this to your npm path
        "runtimeArgs": [
            "run-script",
            "start",
            "--",
            "--inspect-brk=9229"
        ],
         "port": 9229
    },

  ]
}
Tudor Ilisoi
  • 2,934
  • 23
  • 25
  • This worked great, except that the npm lifecycle of it calling `prestart` doesn't work, any idea how to work around that? – CyberMew Dec 05 '20 at 12:02
9

This is how my launch.json looks like, and it works:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch via NPM",
            "request": "launch",
            "runtimeArgs": [
                "run-script",
                "dev"
            ],
            "runtimeExecutable": "npm",
            "skipFiles": [
                "<node_internals>/**"
            ],
            "type": "pwa-node"
        }
    ]
}
4

I tried the solutions given by GutiMac and Jpierson but for some reasons I was not able to make the debugger work with any of those.

An alternative solution which worked fine for me (Ubuntu 16, node 8.9.1, VS 1.8.1) is to use this simple app launcher (to be added in the configuration array of VS launch.json):

{
  "type": "node",
  "request": "launch",
  "name": "Launch Node App",
  "program": "${workspaceFolder}/my-app/my-npm-start-script-dir/index.js"
}
claudod
  • 815
  • 8
  • 8
4

I haven't found a solution how to pass --inspect-brk=9229 to node when you are running external npm run scripts. So here is a solution for the workaround launch configuration.

If you want to debug external npm scripts with parameters or even chain of scripts, you can run them directly from node. For example such scripts as angular-cli run scripts:

"scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
},

Most of external scrips live in node_modules/bin folder. You just need to find you script and figure out what js file it runs. For ng it node_modules/@angular/cli/bin/ng. So here is final launch configuration:

{
    "type": "node",
    "request": "launch",
    "name": "Launch ng build",
    "runtimeExecutable": "node",
    "runtimeArgs": [
        "--inspect-brk=9229",
        "node_modules/@angular/cli/bin/ng"
    ],
    "args": ["build"],
    "port": 9229
}

So when you are starting debuging you get next command started:

node --inspect-brk=9229 node_modules/@angular/cli/bin/ng build

Now you are able to put a breakpoint to external scripts.

Robin B
  • 1,066
  • 1
  • 14
  • 32
drxwat
  • 41
  • 2
4

Most simple and straightforward solution for me. This will compile .ts files into .js and then run the node app in debug mode

.vscode/launch.json


{
   "version": "0.2.0",
   "configurations": [
       {
           "name": "Launch via NPM",
           "request": "launch",
           "runtimeArgs": [
               "run",
               "debug_my_app"
           ],
           "runtimeExecutable": "npm",
           "skipFiles": [
               "<node_internals>/**"
           ],
           "type": "pwa-node"
       }
   ]
}

package.json

{
  "dependencies": {
    "axios": "^0.24.0"
  },
  "scripts": {
    "debug_my_app": "tsc && node index.js"
  }
}

start the debugger

enter image description here

Nika Tsogiaidze
  • 949
  • 14
  • 18
2

My situation was a little different. I was testing an api server and also a client (for that api server). this is what worked for me.

package.json (of the api server)

  "scripts": {
    "start": "DEBUG=users:* PORT=3333 SEQUELIZE_CONNECT=models/sequelize-sqlite.yaml node user-server",
    "debug": "DEBUG=users:* PORT=3333 SEQUELIZE_CONNECT=models/sequelize-sqlite.yaml node --inspect-brk user-server"
  },

launch.json (of the api server)

"configurations": [
    {
        "type": "node",
        "request": "attach",
        "name": "Attach to Remote",
        "address": "localhost",
        "port": 9229,
        "localRoot": "${workspaceFolder}",
        "remoteRoot": "${workspaceFolder}",
        "skipFiles": [
            "<node_internals>/**"
        ]
    },

with that done, I would do the following.

  • npm run debug
  • you should immediately get something like this - Debugger listening on ws://127.0.0.1:9229/8df6503b-00e9-43da-ac53-c54a013ba53f
  • Attach to (in the debug menu) "Attach to Remote" (or whatever name you gave if you have multiple debug configurations) and then hit Run.
  • if successful, you will immediately see something like this - Debugger attached

That would run the api server, and also have the debugger start debugging for me.

Finally, to actually test the api client, I would run the api client file like this. note - all files are in the root folder. if your files are distributed elsewhere, you will have to modify the localRoot and remoteRoot accordingly.

PORT=3333 node users-add-testthisman1.js

Here, its important to note the client configuration I had.

 var client = restify.createJsonClient({
  url: 'http://localhost:'+process.env.PORT,
  version: '*'
});

If you have a different configuration, then, your command line will have different arguments, of course.

Jay
  • 2,648
  • 4
  • 29
  • 58
  • 1
    Very useful. One detail, If you are using a watcher that restarts the process when files are modified, add these two options to launch.json so that the debugger reconnects automatically: `"restart": true, "timeout": 1000` – Dicren May 23 '21 at 18:25
-1

Easiest method I got to work:


1. Inside package.json:

"scripts": {
  "startDebug": "node --inspect index.js"
}

(Note: Does not work with --inspect-brk, for some reason.)


2. In VSCode: Ctrl+Shift+P => Debug: Toggle Auto Attach => Only with flag (Only auto attach when the '--inspect' flag is given)

It should now say Auto Attach: With Flag at the bottom of VSCode.


3. In VSCode Terminal: npm run startDebug

This should run your script in debugger mode, with working breakpoints.

Andrew
  • 5,839
  • 1
  • 51
  • 72
-7

NPM scripts and gulp is not really meant for launching your application, but rather for running tasks like compilation. If it is a node application, I would recommend you to configure your launch.json that way without npm. If you have complicated listeners or process managers like PM2, instead start your application manually from the process manager and then use an Attach configuration.

For npm tasks, you can specify a tasks.json with "command": "npm" and "args": ["run"].

felixfbecker
  • 2,273
  • 1
  • 19
  • 24
  • I haven't had luck with the attach option but I also haven't tried really hard assuming I would run into similar problems. Any documentation that you could point to on how to attach to node when node is not run directly - such as through gulp, webpack, or npm, or all three at the same time :( - would be helpful. – jpierson Jan 21 '16 at 18:56
  • 8
    BTW, the trend that I see emerging is to make `npm start` the standard way to launch a node application. – jpierson Jan 21 '16 at 18:57
  • 1
    gulp is just a NodeJS script itself. You can point "program" to "./node_modules/gulp/bin/gulp.js" (install gulp as devDependency) and set the task name in the args array. – felixfbecker Jan 21 '16 at 19:08
  • 1
    For attach, you need to pass Node the argument --debug-brk to break on the first line and wait for connections. Which means you have to start gulp or whatever through node --debug-brk node_modules/gulp/bin/gulp , then you can attach. – felixfbecker Jan 21 '16 at 19:11
  • 1
    "NPM scripts ... not really meant for launching your application" This is very wrong. `npm start`? Did you miss that? npm start runs the script in your scripts.start config. – jcollum Jul 07 '16 at 17:41
  • The point is that if you want a great debugging experience, you should directly launch the file in your launch.json – felixfbecker Jul 09 '16 at 08:45