Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debugger not binding breakpoints in VSCode in server components, using official Next.js debugger setup #62008

Open
andrewmartin opened this issue Feb 13, 2024 · 45 comments
Labels
bug Issue was opened via the bug report template.

Comments

@andrewmartin
Copy link

andrewmartin commented Feb 13, 2024

Link to the code that reproduces this issue

https://github.com/andrewmartin/nextjs-example

To Reproduce

  1. Open the code in VSCode
  2. Add a breakpoint in any server side files
  3. Open the "Run and Debug" panel
  4. Select "Next.js: debug full stack" and press "F5" or the play button
  5. Note that breakpoints don't land when requests are made in either scenario.

Breakpoints set in server components that aren't attached (sorry the screencaps below didn't show my mouse hover so here's a gif):

Zight Recording 2024-02-13 at 09 45 03 AM

page tsx — tmp2 2024-02-13 at 9 36 58 AM
route ts — tmp2 2024-02-13 at 9 38 08 AM

Debug diagnostics:

Debug Diagnostics — tmp2 2024-02-13 at 9 39 02 AM

Some of the sources loaded (I can provide more if needed):

Debug Diagnostics — tmp2 2024-02-13 at 9 39 53 AM

Current vs. Expected behavior

Hi everyone! The code repo shared is a brand new, blank create-next-app using Typescript, Next 14, and the app directory. I only added the debugging setup from the official docs and a single basic API endpoint at /api/health and that's it. For some reason I cannot for the life of me get my breakpoints to attach.

Well, that's partially true, The only breakpoints that seem to be mapped with my codebase are those in the Browser / client side components. I have tried SO many things to get this to work and have read probably about 30 posts about trying to fix this.

I'd love to know if anyone has any ideas why a vanilla Next.js project might not find my sources. Thanks in advance for your help!

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:44 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6000
Binaries:
  Node: 20.11.0
  npm: 10.2.4
  Yarn: 1.22.21
  pnpm: N/A
Relevant Packages:
  next: 14.1.0
  eslint-config-next: 14.1.0
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Not sure

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

I have tried:

  • Using blank (vanilla) VSCode insiders
  • Using alternative node versions (node 18, other minor node 20)
  • Tried mucking around with the launch config a bit, like adjusting sourceMapPathOverrides etc

Some of my colleagues have had luck seeing them, others have not.

@andrewmartin andrewmartin added the bug Issue was opened via the bug report template. label Feb 13, 2024
@andrewmartin andrewmartin changed the title Debugger examples not working in VSCode on latest version Debugger not binding breakpoints in VSCode in server components, using official Next.js debugger setup Feb 13, 2024
@dmitrc
Copy link

dmitrc commented Feb 14, 2024

I've been facing the same issue, and ultimately the discussion in #56702 is what helped me solve it.

Add the following launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      }
    },
    {
      "name": "Next.js: debug client-side",
      "type": "msedge",
      "request": "launch",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      }
    }
  ]
}

If you're not using Turbopack, replace sourceMapPathOverrides with:
(haven't tried this one)

"sourceMapPathOverrides": {
  "webpack://_N_E/*": "${webRoot}/*"
}

I definitely did not need to do this back in the day (13.5.x for sure), so something must have regressed relatively recently.

@andrewmartin
Copy link
Author

Thanks @dmitrc , and thank you for referencing #56702 which I found helpful too

I actually tried this and it still didn't seem to pick things up. Keep in mind I'm specifically working with server files, e.g. route.ts files in this workflow. I've had some (limited) success grabbing Browser breakpoints.

To be doubly clear, I'm hoping to debug against server code in Next.js, not just the browser.

I'm wondering if there's some other path to consider to include or index on the sourcemaps from route.ts files.

@dmitrc
Copy link

dmitrc commented Feb 14, 2024

@andrewmartin, just to confirm, while the other thread is named "client-side debugging", for my case I was actually also looking to fix the issues with debugging server files specifically (page.tsx), and following the steps outlined above helped.

@andrewmartin
Copy link
Author

@dmitrc totally I get it. Thanks much. I still am struggling :(

@dmitrc
Copy link

dmitrc commented Feb 14, 2024

I hope your thread can get some attention from the team -- debugging is such a core part of development experience, it's in everyone's best interest to get this fixed and/or clarified ASAP. Best of luck with your scenario!

@andrewmartin
Copy link
Author

Thanks a lot and totally agree! It worked so nicely before next 14.

@andrewmartin
Copy link
Author

#62008 (comment)

Just so y'all know, this did not work for me. @dmitrc did this work for you with API endpoints (not just the actual page.tsx files?)

@albert-kovalevskij
Copy link

albert-kovalevskij commented Feb 28, 2024

Neither worked for me, tried to follow @dmitrc suggestion but this didn't work for me, that unacceptable, can we fix it, please

P.S. https://nextjs.org/docs/pages/building-your-application/configuring/debugging just being stupid and not reading the docs, actually it worked perfectly by setting "cwd": "${workspaceFolder}/apps/web" for turporepo

@alamit
Copy link

alamit commented Mar 9, 2024

Also struggling with this, can't manage to make server side debugging work

@avianion
Copy link

@andrewmartin still getting this issue when using turbopack on server files with the vscode debugger, did ou fix it

@zanhk
Copy link

zanhk commented Mar 23, 2024

having the same problem as well, does anyone found a solution?

@avianion
Copy link

@x-yuri
might know

@andrewmartin
Copy link
Author

@avianion Yeah, still hitting it unfortunately. I kinda gave up. It's odd because some projects, it works totally fine, like the T3 starter apps. I really can't surmise any meaningful differences in the setup, either.

@avianion
Copy link

The .js files seem to be generated fine, but the corresponding .map files are not found. See here my debugger says

Could not read source map for file:///app/nextjs/.next/server/chunks/e95bda..js: ENOENT: no such file or directory, open 'c:\Users\my_user\Desktop\my_app\nextjs\nextjs.next\server\chunks_e95bda._.js.map'

however the e95bda..js file is itself present, just not the map.

@jensenrrr
Copy link

@albert-kovalevskij Had the solution for me. This only affects those using turborepo.

"P.S. https://nextjs.org/docs/pages/building-your-application/configuring/debugging just being stupid and not reading the docs, actually it worked perfectly by setting "cwd": "${workspaceFolder}/apps/web" for turporepo"

@daguej
Copy link

daguej commented Mar 28, 2024

I've been unable to get next dev to properly start up with debugging enabled. If I use the launch config suggested in the docs, node simply isn't launched with debugging enabled at all. If I try manually, eg:

$ npx --node-options='--inspect' next dev
Debugger listening on ws://127.0.0.1:9229/66073dfe-7554-4b37-8d8d-e4f7dc47789d
For help, see: https://nodejs.org/en/docs/inspector
Starting inspector on 127.0.0.1:9229 failed: address already in use

…this results in the parent next dev process running with debugging, but the worker subprocess tries to debug on the same port, which fails.

I was able to at least get debugging working by starting plain next dev with no debugging enabled, then sending SIGUSR1 to the next-router-worker subprocess spawned by the next dev process. I can then use VS Code to attach to the worker process.

This is a painful workaround; something in Next needs to be fixed to make debugging work properly.

@nassud
Copy link

nassud commented Mar 28, 2024

In all scenarios debugger attaches for me just fine but breakpoints do not bind. I'm guessing is just related to it being unable to find the files. I'm using these configs:

{
      "name": "Next.js: Attach",
      "port": 9230,
      "request": "attach",
      "skipFiles": ["<node_internals>/**"],
      "type": "node",
      "localRoot": "${workspaceFolder}/my-app/src"
    },
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "webpack://_N_E/*": "${webRoot}/*"
      },
      "cwd": "${workspaceFolder}/may-app"
    },

Nothing seems to work

@dexxiez
Copy link

dexxiez commented Apr 4, 2024

Hi all,

I've just been down this rabbit hole and its terrible. By a stroke of luck, I could get it working. I might be repeating what is already said here, just from a different perspective which may help someone.

Full degression, running Next 14.1.4, Node v20.11.0 (LTS) (in WSL - probably irrelevant, so I'll just say Ubuntu). I've tested it in pages and app router.

This is the first time I've actually been able to get a NodeJS application actually to debug, and I can't believe it.

My environment is turborepo (soon to be nx, but thats another story).

I can confirm my relative path to next is apps/web from the root. and in the end, it didn't matter anyway.

My symptoms were a lot the same as the others here, client side is perfect, server side might as well be located in Mars for all I knew. I looked in the NodeJS debug tool and saw that only a subset of my server files were actually being exposed.

image

After actually using my eyes 👀 I saw this.

> NODE_OPTIONS='--inspect' next dev

Debugger listening on ws://127.0.0.1:9229/99f15ee9-6b51-46b4-a070-ccc8bcb60e76
For help, see: https://nodejs.org/en/docs/inspector
Debugger listening on ws://127.0.0.1:9230/42518e76-ee66-44ea-9cb5-a575f1d5fd0c
For help, see: https://nodejs.org/en/docs/inspector
   the --inspect option was detected, the Next.js router server should be inspected at port 9230.

Now call me stupid or ADHD riddled, but I stopped looking normally at the first line mentioning port 9229. It sneaks in 9230 which i found the NodeJS debug tool via Chrome does NOT add by default. At this point I didn't go straight to vscode. I stayed with the Node debugger to do some more testing. I added it in.

image

After adding it in and probably restarting the dev server with the documented normal command via Package JSON script

{
....
"scripts": {
"debug": "NODE_OPTIONS='--inspect' next dev",
}
...

I looked at the sources tab in Node Devtools

image

and it actually had web listed there which is the folder NextJS is in (as im running monorepo). My cardiovascular signs increased. I then added a breakpoint in the Chrome devtools using the file explorer in sources and clicking on a line number in the file previewer.

image

I ran the code, and the breakpoint tripped. I thought I was tripping instead to be honest, this is the closest I've ever gotten.

Only now did I go back to VSCode Debug

I made the new debug file which I've rage deleted many times.

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Attach to Node",
            "port": 9230,
            "skipFiles": [
                "<node_internals>/**"
            ],
            "cwd": "${workspaceFolder}/apps/web" // I have this because it lives in subfolders, if you're soloing it with no monorepo, you can remove this
        },
        // Below is irrelevant to this post but whatever
        {
            "name": "Next.js: debug client-side",
            "type": "chrome",
            "request": "launch",
            "url": "http://localhost:3000",
            "cwd": "${workspaceFolder}/apps/web",
        },
    ]
}

IMPORTANT SIDE NOTE: This does not start your dev server, it purely connects to what is running, so start your dev server with inspect as per previous Package JSON mention.

The debugger attached but breakpoints are still not red/are hollow with no fill. I tried it anyway, and it worked.

image

Things that did not work for me

  • Preserve symlinks message said to add the argument, I got worse errors so I removed it.
  • Adding a source maps override
  • Adding the outFiles pointing to the .next directory. While it technically did work, vscode would only show the webpack compiled version which is better than nothing, but is yucky none the less.

Things that may be useful troubleshooting

Everyone mentions ${workspaceFolder} in their configurations, but if you are unsure what it is, or you have doubts vscode is selecting the right one, use this echo task to double check it. It's for Linux/WSL so adopt to Windows how you see fit. or ChatGPT it.

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "echo ${workspaceFolder}"
        }
    ]
}

I hope this helps you on your journey of accelerated hair loss.

@DrPye
Copy link

DrPye commented Apr 22, 2024

Hi all, I just wanted to add what I've been using with the app router to get my debugging working as similar to the pages method in the docs. The main thing ive added compared to other suggestions is the ability to debug the full stack in one task.

Tested on Windows with WSL(ubuntu) and using the regular VSCode

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev --turbo"
    },
    {
      "name": "Next.js: debug client-side",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000"
    },
    {
      "name": "Next.js: debug full stack",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev --turbo",
      "skipFiles": ["<node_internals>/**"],
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      },
      "serverReadyAction": {
        "action": "debugWithEdge",
        "killOnServerStop": true,
        "pattern": "- Local:.+(https?://.+)",
        "uriFormat": "%s",
        "webRoot": "${workspaceFolder}"
      }
    }
  ]
}

@togakangaroo
Copy link

Here to say that I finally got this working after a bunch of frustration (using node inspector, I don't tend to use vscode for js debugging usually). The big key was this comment so thank you @dexxiez

Some notes on that

  • Firstly I had to run NODE_OPTIONS='--inspect' next dev
  • Then I pointed my browser to chrome://inspect and opened the inspector
  • I went to the connections tab and added one for localhost:9230
  • I shut down the server and then I shut down the inspector
  • I restarted the server in the same manner
  • Now in chrome://inspect I saw a second option
    screenshot of chrome inspect page showing two options now available
  • I clicked inspect on the second one (the one with start-server) and could actually find next's server in start-server.js. This is promising since it runs in the same process as my code.
  • Now here's the trick, this didn't actually result in my code being visible in node inspector until I actually pointed my browser at the localhost:3000 app and let it load some pages. Only then could I CMD+P and find some of my typescript files. Once I did I could set breakpoints and those breakpoints get hit!

Therefore the trick seems to be to first of all add the appropriate connection, but then also to launch the process, let pages load, and only then try to connect to it via the debugger.

@TechGeorgii
Copy link

TechGeorgii commented Jun 7, 2024

A very simple setup that got it working for me.

In package.json I specified Node inspect port option (default was busy by another project):

"scripts": {
    "dev": "NODE_OPTIONS='--inspect=9237' next dev"
  },

then I run my project npm run dev.

in launch.json :

    {
      "type": "node",
      "request": "attach",
      "name": "Attach to front-end",
      "port": 9238,   // note port is +1 of what's specified in inspect.
      "skipFiles": [
          "<node_internals>/**"
      ],
      "cwd": "${workspaceFolder}/front-end" // I have front-end dir in the workspace, use your setup
    },

And then run attach in VSCode. Breakpoints are working!

Note that ports do not match – I don't know why but node was always starting on port+1 on specified!! (you can see actual port it started in the console).

@0x33dm
Copy link

0x33dm commented Jun 9, 2024

@dmitrc it actually worked with your config. what a ride! took me ages to find your answer. thank you!

@apferrarone
Copy link

apferrarone commented Jun 13, 2024

I tried so many things. I am running a TS monolithic Next.js app, and turns out all I needed to do was turn on auto-attach VSCode feature and launch the app from the VSCode terminal. No configurations or changes, I deleted everything - just run npm run dev from the VSCode terminal w/ auto-attach set to "Always" and it found all the Node processes and the breakpoints are working. To be clear I am just debugging server-side code but this is working for me 🤷‍♂️

@0x33dm
Copy link

0x33dm commented Jun 13, 2024

I tried so many things. I am running a TS monolithic Next.js app and it turns out all I needed to do was turn on the auto-attach the VSCode feature and launch the app from the VSCode terminal. No configurations or changes, I deleted everything - just run npm run dev from the VSCode terminal w/ auto-attach set to "Always" and it found all the Node processes and the breakpoints are working. To be clear I am just debugging server-side code but this is working for me 🤷‍♂️

The same is true for most projects. If you have it to auto-attach "always," there is a good chance it will work when you run it from the terminal. It needs to be "always," apparently, because sometimes a process will launch another and another, and apparently, "always" covers those cases.

In other cases, for instance, in my case, we use turborepo, so we had to do the mapping described by @dmitrc

The browser code is slightly different because the browser needs to be launched with the parameters to allow remote connection on the Chrome inspector.

@zanhk
Copy link

zanhk commented Jul 7, 2024

Does someone have a sample repo where debugging work on windows with turbopack?

@0x33dm
Copy link

0x33dm commented Jul 8, 2024

Does someone have a sample repo where debugging work on windows with turbopack?

try this

.vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "pnpm run dev",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      }
    },
    {
      "name": "Next.js: debug client-side",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      }
    }
  ]
}

@zanhk
Copy link

zanhk commented Jul 8, 2024

Thanks @0x33dm but unfortunatly with that configuration it does not work

With either "dev": "cross-env NODE_OPTIONS='--inspect' next dev --turbo", or "dev": "cross-env NODE_OPTIONS='--inspect=9230' next dev --turbo", or "dev": "next dev --turbo",

D:\repositories\novafyapp\nova-dogs>bun run dev
$ cross-env NODE_OPTIONS='--inspect=9230' next dev --turbo
Debugger attached.
Starting inspector on 127.0.0.1:9230 failed: address already in use
Starting inspector on 127.0.0.1:9231 failed: address already in use
 ⚠ Port 3000 is in use, trying 3001 instead.
   the --inspect option was detected, the Next.js router server should be inspected at port 9231.
  ▲ Next.js 14.2.4 (turbo)
  - Local:        http://localhost:3001
  - Environments: .env

 ✓ Starting...
 ✓ Ready in 1603ms

It doesn't hit neither the breapoints on server side neither the ones on client side

The only way i got it to work is without using turbo with this config

{
	"version": "0.2.0",
	"configurations": [
		{
			"name": "server",
			"type": "node-terminal",
			"request": "launch",
			"command": "bun run dev"
		},
		{
			"name": "client",
			"type": "chrome",
			"request": "launch",
			"url": "http://localhost:3000"
		},
		{
			"type": "node",
			"request": "attach",
			"name": "attach",
			"port": 9231,
			"skipFiles": ["<node_internals>/**"]
		}
	],
	"compounds": [
		{
			"name": "Debug Server and Client",
			"configurations": ["server", "client", "attach"]
		}
	]
}

"dev": "cross-env NODE_OPTIONS='--inspect=9230' next dev",

But with webpack is slow af

@dexxiez
Copy link

dexxiez commented Jul 8, 2024

Port 3000 is in use, trying 3001 instead.

@zanhk You may have a secret session running somewhere which might cause this to occur ⬇️

Starting inspector on 127.0.0.1:9230 failed: address already in use
Starting inspector on 127.0.0.1:9231 failed: address already in use

I'd try looking for double process sneaking in somewhere.

But with webpack is slow af

It's got its charm.

@zanhk
Copy link

zanhk commented Jul 9, 2024

@dexxiez In the previous snippet I just forgot the other session running, but I have the problem anyway

$ cross-env NODE_OPTIONS='--inspect=9230' next dev --turbo
Debugger attached.
Debugger listening on ws://127.0.0.1:9230/d1ff749b-87c1-487d-96d7-8d58eb67b8bf
For help, see: https://nodejs.org/en/docs/inspector
Debugger listening on ws://127.0.0.1:9231/8a113e34-44a3-4a55-832c-3e2cfa61b27a
For help, see: https://nodejs.org/en/docs/inspector
   the --inspect option was detected, the Next.js router server should be inspected at port 9231.
  ▲ Next.js 14.2.4 (turbo)
  - Local:        http://localhost:3000
  - Environments: .env

 ✓ Starting...
 ✓ Ready in 1682ms

Also with the working example above with webpack it does not hit server breakpoints consistenly

@dexxiez
Copy link

dexxiez commented Jul 9, 2024

@zanhk hmmm hard one, I don't have much experience with Turbopack myself as it's incompatible with most options I run. I try it every so often to check in on it, and the foot guns come out blazing. I can see you're running Windows which also throws a spanner in the works for me. UNIX based development is definitely getting standardized across the board it seems and probably for good reason. I daily drive Linux so I'm probably biased as all hell here, but there's a reason why all the Tec-bros use Macs. If it's not a compatibility/technical reason and it might be a knowledge gap you might have, I'd look at filling that gap looking into the future of development for you. This is not an excuse for any of this not to work, but us at the bottom of the food chain need to convince technology to work somehow, and UNIX/Linux environments just work a bit better at rolling the dice. WSL is an amazing middle ground between being bankrupt and no lifeing things with daily driving Linux like me.

What i just wrote will be probably no help to you whatsoever, but I thought I'd entertain you while someone who knows what they are talking about with Turbo chimes in.

@jonathan-sotelo
Copy link

I fixed this by creating a nodemon.json file on the root of the project, but be aware that I'm not using the latest Next.js version:

{
  "env": {
    "NODE_OPTIONS": "--inspect"
  }
}

This will pass the environment variable only on the Node process that is needed to debug. This is considering also that is run from package.json as next dev (or npx next dev from launch.json).
In my case, launch.json looks like the official docs:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev"
    },
  ]
}

@x-yuri
Copy link

x-yuri commented Jul 21, 2024

Since @avianion has summoned me, I can't just go past I guess :) A bit late, but sorry, a lot of work.

Taking the steps from the original post and amending them a bit to make it more specific, to not involve the client-side debugging parts (I use the server-side launch.json configuration, because it similarly does not work), and well... I prefer Firefox:

  • git clone https://github.com/andrewmartin/nextjs-example
  • Open the project in vscode.
  • Open src/app/page.tsx and set a breakpoint at the beginning of the Home() function.
  • npm i
  • Run (F5). I expect the server-side launch.json configuration to be chosen, which is the default, unless you chose the other configuration in the past.
  • Open a browser at http://localhost:3000 after nextjs is ready.

Then:

  • Enable tracing in launch.json by adding "trace": {"logFile": "/tmp/a.log"} to the server-side configuration.
  • Add console.log(`-- home: ${Date.now()}`) before the breakpoint.
  • Add the following lines before/after the line (node_modules/next/dist/server/require.js) that requires .next/server/app/page.js:
    console.log(`-- before require: ${Date.now()}`)
    console.log(`-- after require: ${Date.now()}`)
  • Add the following lines before/after the line (node_modules/next/dist/server/base-server.js) that renders the page and executes the Home() function:
    console.log(`-- before render: ${Date.now()}`)
    console.log(`-- after render: ${Date.now()}`)
  • Stop the project (Shift-F5).
  • Start it again (F5) and refresh the page in the browser after nextjs is ready.
$ grep 'setBreakpoint\|scriptParsed' /tmp/a.log
...
{"tag": "cdp.send",
 "timestamp": 1721504246.294,
 "metadata": {
   "message": {
     "method": "Debugger.setBreakpointByUrl",
     "params": {
       "urlRegex": "file:\\/\\/\\/home\\/yuri\\/tmp\\/nextjs-example\\/src\\/app\\/page\\.tsx($|\\?)|\\/home\\/yuri\\/tmp\\/nextjs-example\\/src\\/app\\/page\\.tsx($|\\?)",
       "lineNumber": 0,
       "columnNumber": 0
     }}}}
{"tag": "cdp.send",
 "timestamp": 1721504246.294,
 "metadata": {
   "message": {
     "method": "Debugger.setBreakpointByUrl",
     "params": {
       "urlRegex": "file:\\/\\/\\/home\\/yuri\\/tmp\\/nextjs-example\\/src\\/app\\/page\\.tsx($|\\?)|\\/home\\/yuri\\/tmp\\/nextjs-example\\/src\\/app\\/page\\.tsx($|\\?)",
       "lineNumber": 4,
       "columnNumber": 0
     }}}}
...
{"tag": "cdp.receive",
 "timestamp": 1721504253.117,
 "metadata": {
   "message": {
     "method": "Debugger.scriptParsed",
     "params": {
       "scriptId": "2316",
       "url": "webpack-internal:///(rsc)/./src/app/page.tsx",
       "sourceMapURL": "<data source map url>",
     }}}}
...
{"tag": "cdp.send",
 "timestamp": 1721504253.125,
 "metadata": {
   "message": {
     "method": "Debugger.setBreakpoint",
     "params": {
       "location": {
         "scriptId": "2316",
         "lineNumber": 11,
         "columnNumber": 4
       }}}}}

And in the terminal pane I see (I separate the milliseconds):

-- before require: 1721504252.841
-- after require: 1721504253.047
-- before render: 1721504253.055
-- home: 1721504253.122
-- after render: 1721504253.404

So what does happen here? You surely understand that you set a breakpoint in a source (TypeScript) file, and vscode can't simply tell nodejs to stop in src/app/page.tsx (unless I'm wrong), because what nodejs executes instead is .next/server/app/page.js. Actually as you can see from the log messages above vscode tries to use the Debugger.setBreakpointByUrl method to do just that, but nodejs doesn't stop.

So how do the breakpoints ever work then? vscode receives from nodejs Debugger.scriptParsed events about every file nodejs loads (imports, requires). With the event comes scriptId which enables vscode to use the Debugger.setBreakpoint method where the file is identified by id. And such breakpoints do work.

Then how does vscode determine that the script in the event matches the one the breakpoint points to (/home/yuri/tmp/nextjs-example/src/app/page.tsx in my case)? With the event also comes sourceMapURL. In this particular case with webpack the source map is right in the URL (data:application/json;charset=utf-8;base64,...). vscode parses the source map, takes from the sources field the URL of the source file. In this case it's 'webpack://tmp2/./src/app/page.tsx?f68a'. Removes the query string, applies sourceMapPathOverrides (the defaults). As a result it gets /home/yuri/tmp/nextjs-example/./src/app/page.tsx. Then it removes the ./ part (/home/yuri/tmp/nextjs-example/src/app/page.tsx). And that's exactly the location of the file where I set the breakpoint. Then vscode finds the breakpoint by path and uses Debugger.setBreakpoint to set the breakpoint. After this point the breakpoint starts to work.

Let's bring nextjs into the picture. nextjs requires .next/server/app/page.js at 1721504253.047, vscode is notified about this at 1721504253.117, the Home() function starts executing at 1721504253.122 and vscode sets the breakpoint at 1721504253.125. In other words nextjs requires page.js and soon executes the Home() function. vscode has to make it in time to set the breakpoint before Home() starts executing. And sometimes it does on my machine. That's what the common folks call a race condition. You can easily confirm this by making the Home() function async and adding the following line before the breakpoint:

await new Promise(r => setTimeout(r, 1000));  // 1000 or more

As for sourceMapPathOverrides, what applies here is webpack://?:*/*': `${webRoot}/*`. ?:* is a non-capturing group (.*?), * is a capturing one ((.*?)). In terms of regular expressions that is /^webpack:\/\/.*?\/(.*?)$/i -> workspaceFolder + '/$1'.

@CMarshall92
Copy link

{
"name": "Next.js: debug server-side",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev",
"sourceMaps": true,
"sourceMapPathOverrides": {
"/turbopack/[project]/": "${webRoot}/"
}
},
{
"name": "Next.js: debug client-side",
"type": "msedge",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"/turbopack/[project]/": "${webRoot}/"
}
}

You sir

I've been facing the same issue, and ultimately the discussion in #56702 is what helped me solve it.

Add the following launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      }
    },
    {
      "name": "Next.js: debug client-side",
      "type": "msedge",
      "request": "launch",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      }
    }
  ]
}

If you're not using Turbopack, replace sourceMapPathOverrides with: (haven't tried this one)

"sourceMapPathOverrides": {
  "webpack://_N_E/*": "${webRoot}/*"
}

I definitely did not need to do this back in the day (13.5.x for sure), so something must have regressed relatively recently.

You are an absolute hero... Seeing as we are using the base setup of next its actually baffling without going into the node debugger and seeing that random turbopack folder... why is it not in the docs come on team....

@patrick-moore
Copy link

A very simple setup that got it working for me.

In package.json I specified Node inspect port option (default was busy by another project):

"scripts": {
    "dev": "NODE_OPTIONS='--inspect=9237' next dev"
  },

then I run my project npm run dev.

in launch.json :

    {
      "type": "node",
      "request": "attach",
      "name": "Attach to front-end",
      "port": 9238,   // note port is +1 of what's specified in inspect.
      "skipFiles": [
          "<node_internals>/**"
      ],
      "cwd": "${workspaceFolder}/front-end" // I have front-end dir in the workspace, use your setup
    },

And then run attach in VSCode. Breakpoints are working!

Note that ports do not match – I don't know why but node was always starting on port+1 on specified!! (you can see actual port it started in the console).

This worked perfectly for me. Thanks for posting!

@spacecat
Copy link

spacecat commented Sep 3, 2024

It's very surprising to me that client side, server side, and full-stack debugging is still not working 100% in Next.js 14 using the App Router.

Also the documentation (https://nextjs.org/docs/app/building-your-application/configuring/debugging) clearly is just a copy and paste of the stuff from the Pages Router. This suggests to me that debugging has not even been tested properly or prioritized.

To Vercel: Please revise the docs. Provide a launch.json that works with the latest version of VSCode. Also, please tell us with screenshots, videos, proper step-by-step on how to setup VSCode. Don't just link to their docs. We as developers should not need to spend an entire day to figure out how to debug our Next.js applications.

Enough with the complains. I literally sat the entire day yesterday trying to figure out how the hell VSCode should be setup in order to get both client-side, server side and full-stack debugging properly without any hacky launch.jsons or other work-arounds. When I want to get something working I want to touch as little as possible of the IDE, settings file etc. So here's my solution - it's not perfect but it's the most non-intrusive and one that I can live with in my day-to-day coding:

Client-Side, Server-Side, Full-Stack Debugging Next.js 14 (App Router) in VSCode

How to Debug (Client Side)

Note: It's okay to have a regular Chrome browser open while debugging in VSCode. The debugger will attach to a NEW Chrome process that you launch from the terminal.

  1. Launch a new Chrome process from the terminal in VSCode by running the following command:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222 --user-data-dir="/Users/your-user-goes-here/vscode-debugger-chrome-profile"

This command is no magic; it's from the official VSCode docs: https://code.visualstudio.com/docs/nodejs/browser-debugging#_attaching-to-browsers

If this is the first time, Chrome will ask if you want to make this your current browser and if you want to send statistics to Google. Select whatever you want in this dialog.

The --user-data-dir flag is used in Chrome and Edge browsers to specify a custom directory for storing user data (such as cookies, local storage, browsing history, etc.) during the browser session. When you use this flag, the browser creates a new profile in the specified directory, separate from your default user profile. For debugging and to keep things isolated and not interfering with one another this is the recommended way.

  1. Create a launch.json file in VSCode and add the following configuration:

Note: You can autogenerate the code below by adding a new configuration and selecting "Chrome: Attach". Also, you can copy and paste the code below in a new launch.json. Put the launch.json in your .vscode folder.

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Attach to Chrome",
            "port": 9222,
            "request": "attach",
            "type": "chrome",
            "webRoot": "${workspaceFolder}"
        }
    ]
}

  1. Open the Debugger in VSCode and select the "Attach to Chrome" configuration that you created in step 3.
  2. Set breakpoints in your code and run the debugger.

Note: I use Clerk as my auth provider and if you use this debugging method, signing in to your Google account via Clerk will work. If you use Nexj.js's method (https://nextjs.org/docs/app/building-your-application/configuring/debugging#debugging-with-vs-code) you will not be able to sign in to your Google account. Keep this in mind when selecting debugging method.

How to Debug (Server Side)

  1. Create a new JavaScript Debug Terminal. (F1 and then type JavaScript Debug Terminal or create a new JavaScript Debug Terminal from your terminal pane by clicking the dropdown beside the plus sign.
  2. Run npm run dev
  3. Set some breakpoint in your .tsx components
  4. Use a regular Chrome window (with your own user profile) to navigate to the page you want to debug.
  5. The breakpoint will be unbound until you run that code in the browser. This is weird and unintuitive and should be improved somehow otherwise how else will you know that your breakpoints are working?

How to Debug (Full-stack)

I tried this by having two debugging sessions (client side and server side like I explained above) but it worked poorly so I would recommend using one method at a time and not both at once.

Notes:

In VSCode settings Debug -> JavaScript: Auto Attach Filter should be set to "Disabled" (This is the default setting). I messed around with this setting thinking it might solve some problems but I honestly don't know how it works exactly so I wanted to make sure I reverted it back to its default setting.

I hope the above helps someone using Next.js 14+ (App Router) trying to debug both client side and server side code using VSCode's debugger.

@yuyakinjo
Copy link

I referred to @dmitrc's configuration and successfully used pnpm with turbopack. Below is the launch.json that worked for me. Thanks!
By pressing F5, both the server-side and browser start and stop, and I can set breakpoints for debugging. The runtimeArgs have been adjusted to match the scripts in the package.json.

// launch.json
{
  "version": "0.2.0",
  "compounds": [
    {
      "name": "Debug Start All",
      "configurations": ["Launch Chrome", "Start Nextjs"],
      "stopAll": true
    }
  ],
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Launch Chrome",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      },
      "presentation": {
        "hidden": true
      }
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Start Nextjs",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      },
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["run", "dev:turbo"],
      "presentation": {
        "hidden": true
      }
    }
  ]
}
// package.json

{
  ...
  "scripts": {
   ...
    "dev:turbo": "next dev --turbo",
  },
  "dependencies": {
    ...
    "next": "^14.2.7",
  },
  ...
}

@tianzhich
Copy link

Have you guys solved this in server-sider api debugging?

@jaredcbaum
Copy link

Here's how I got it working using this setup:

Next.js 15.0.0.rc (webpack)
Turborepo 2.x.x

#66699 (comment)

@trozzelle
Copy link

For anyone using > Next.js 14.2, the source map path has changed, per #63740 (comment):

        // Old Turbopack path
        "/turbopack/[project]/*": "${workspaceFolder}/*",
        // New Turbopack path
        "turbopack://[project]/*": "${workspaceFolder}/*"

I'm running the 14.2.3 canary and breakpoint debugging suddenly broke. Changing the sourceMapPathOverrides path like above fixed it for me.

@Rexiao
Copy link

Rexiao commented Oct 8, 2024

For people using

"dependencies": {
    "next": "14.2.14",
}

Here is what works for me:

{
  "version": "0.2.0",
  "compounds": [
    {
      "name": "Debug Start All",
      "configurations": ["Launch Chrome", "Start Nextjs"],
      "stopAll": true
    }
  ],
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Launch Chrome",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      },
      "presentation": {
        "hidden": true
      }
    },
    {
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev",
      "name": "Start Nextjs",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      },
      "presentation": {
        "hidden": true
      }
    }
  ]
}

thanks to #62008 (comment)

@sathishkannan162
Copy link

sathishkannan162 commented Oct 17, 2024

{
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: debug server-side",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev",
"sourceMaps": true,
"sourceMapPathOverrides": {
"/turbopack/[project]/": "${webRoot}/"
}
},
{
"name": "Next.js: debug client-side",
"type": "msedge",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"/turbopack/[project]/": "${webRoot}/"
}
}
]
}

This worked for me. It even worked for server actions. I am using turbopack for local development and using Next.js v14.2.14. thanks @dmitrc for the configuration

@matija2209
Copy link

For people using

"dependencies": {
    "next": "14.2.14",
}

Here is what works for me:

{
  "version": "0.2.0",
  "compounds": [
    {
      "name": "Debug Start All",
      "configurations": ["Launch Chrome", "Start Nextjs"],
      "stopAll": true
    }
  ],
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Launch Chrome",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      },
      "presentation": {
        "hidden": true
      }
    },
    {
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev",
      "name": "Start Nextjs",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/*"
      },
      "presentation": {
        "hidden": true
      }
    }
  ]
}

thanks to #62008 (comment)

Thanks you @Rexiao. This worked for me on 14.2.15 as well. It's the only code that worked.

My package.json script is

"debug": "next dev --turbo --port 4040",

@fcFn
Copy link

fcFn commented Nov 4, 2024

This worked for me after some time (using Nx):

launch.json:

...
{
      "name": "Next.js: debug server-side",
      "type": "node",
      "request": "attach",
      "sourceMaps": true,
      "port": 9230, // Note the port is not the default 9229
      "cwd": "${workspaceFolder}/apps/my-app",
      "sourceMapPathOverrides": {
        "webpack:///./*": "${webRoot}/apps/my-app/*"
 }
 ...

project.json

...
"serve": {
     "command": "cross-env NODE_OPTIONS='--inspect' next dev",
     "defaultConfiguration": "development",
     "production": {},
     "staging": {}
   }
...

Then I would launch npx serve my-app and launch the configuration in VS Code which made the breakpoints hit inside page.tsx. Make sure you're actually opening your page in the browser, otherwise the breakpoints would not hit.

@drollinger
Copy link

drollinger commented Nov 20, 2024

This is what ended up working for me. Using webpack-internal instead. Also, not using the standard port 9229 due to how I have things set up.

"configurations": [
    {
      "name": "Debug Webapp",
      "type": "node",
      "request": "attach",
      "port": 9230,
      "cwd": "${workspaceFolder}/packages/webapp",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "webpack-internal:///(rsc)/./*": "${webRoot}/packages/webapp/*"
      }
    },

I found this running the chrome node inspector, hooking it up to the correct port, setting a break point that successfully triggered. Then opening the terminal debugger with node inspect localhost:9230 and triggering the break point and node inspector output the file path of the break point

connecting to localhost:9230 ... ok
break in webpack-internal:///(rsc)/./src/app/api/{..rest of path}

There may be an easier way to find this info but worked for me

@nickwinger
Copy link

Hi all,

I've just been down this rabbit hole and its terrible. By a stroke of luck, I could get it working. I might be repeating what is already said here, just from a different perspective which may help someone.

Full degression, running Next 14.1.4, Node v20.11.0 (LTS) (in WSL - probably irrelevant, so I'll just say Ubuntu). I've tested it in pages and app router.

This is the first time I've actually been able to get a NodeJS application actually to debug, and I can't believe it.

My environment is turborepo (soon to be nx, but thats another story).

I can confirm my relative path to next is apps/web from the root. and in the end, it didn't matter anyway.

My symptoms were a lot the same as the others here, client side is perfect, server side might as well be located in Mars for all I knew. I looked in the NodeJS debug tool and saw that only a subset of my server files were actually being exposed.

image

After actually using my eyes 👀 I saw this.

> NODE_OPTIONS='--inspect' next dev

Debugger listening on ws://127.0.0.1:9229/99f15ee9-6b51-46b4-a070-ccc8bcb60e76
For help, see: https://nodejs.org/en/docs/inspector
Debugger listening on ws://127.0.0.1:9230/42518e76-ee66-44ea-9cb5-a575f1d5fd0c
For help, see: https://nodejs.org/en/docs/inspector
   the --inspect option was detected, the Next.js router server should be inspected at port 9230.

Now call me stupid or ADHD riddled, but I stopped looking normally at the first line mentioning port 9229. It sneaks in 9230 which i found the NodeJS debug tool via Chrome does NOT add by default. At this point I didn't go straight to vscode. I stayed with the Node debugger to do some more testing. I added it in.

image

After adding it in and probably restarting the dev server with the documented normal command via Package JSON script

{
....
"scripts": {
"debug": "NODE_OPTIONS='--inspect' next dev",
}
...

I looked at the sources tab in Node Devtools

image

and it actually had web listed there which is the folder NextJS is in (as im running monorepo). My cardiovascular signs increased. I then added a breakpoint in the Chrome devtools using the file explorer in sources and clicking on a line number in the file previewer.

image

I ran the code, and the breakpoint tripped. I thought I was tripping instead to be honest, this is the closest I've ever gotten.

Only now did I go back to VSCode Debug

I made the new debug file which I've rage deleted many times.

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Attach to Node",
            "port": 9230,
            "skipFiles": [
                "<node_internals>/**"
            ],
            "cwd": "${workspaceFolder}/apps/web" // I have this because it lives in subfolders, if you're soloing it with no monorepo, you can remove this
        },
        // Below is irrelevant to this post but whatever
        {
            "name": "Next.js: debug client-side",
            "type": "chrome",
            "request": "launch",
            "url": "http://localhost:3000",
            "cwd": "${workspaceFolder}/apps/web",
        },
    ]
}

IMPORTANT SIDE NOTE: This does not start your dev server, it purely connects to what is running, so start your dev server with inspect as per previous Package JSON mention.

The debugger attached but breakpoints are still not red/are hollow with no fill. I tried it anyway, and it worked.

image

Things that did not work for me

  • Preserve symlinks message said to add the argument, I got worse errors so I removed it.
  • Adding a source maps override
  • Adding the outFiles pointing to the .next directory. While it technically did work, vscode would only show the webpack compiled version which is better than nothing, but is yucky none the less.

Things that may be useful troubleshooting

Everyone mentions ${workspaceFolder} in their configurations, but if you are unsure what it is, or you have doubts vscode is selecting the right one, use this echo task to double check it. It's for Linux/WSL so adopt to Windows how you see fit. or ChatGPT it.

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "echo ${workspaceFolder}"
        }
    ]
}

I hope this helps you on your journey of accelerated hair loss.

Thank you, this is also working on my side now. I also had the feeling that there are to many processes started for debugging on different ports, however just attaching the VSCode to the 9230 running process is the easiest way.
So on my side i started "turbo dev" in an external command line and then attached VSCode like you said. Also the breakpoints are red and working on server side !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests