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

Debugging with NODE_OPTIONS='--inspect=0.0.0.0' next dev causes errors #53127

Closed
1 task done
mkoreo opened this issue Jul 24, 2023 · 21 comments · Fixed by #65006
Closed
1 task done

Debugging with NODE_OPTIONS='--inspect=0.0.0.0' next dev causes errors #53127

mkoreo opened this issue Jul 24, 2023 · 21 comments · Fixed by #65006
Labels
bug Issue was opened via the bug report template. locked

Comments

@mkoreo
Copy link

mkoreo commented Jul 24, 2023

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: linux
      Arch: x64
      Version: #1 ZEN SMP PREEMPT_DYNAMIC Tue, 04 Jul 2023 08:39:22 +0000
    Binaries:
      Node: 20.3.1
      npm: 8.19.2
      Yarn: N/A
      pnpm: 8.6.6
    Relevant Packages:
      next: 13.4.12
      eslint-config-next: 13.0.0
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.1.6
    Next.js Config:
      output: N/A

Which area(s) of Next.js are affected? (leave empty if unsure)

No response

Link to the code that reproduces this issue or a replay of the bug

https://github.com/vercel/next.js/blame/8d83d85e5359146bbbd0f96ea2f8490e7d6bc9cd/packages/next/src/cli/next-dev.ts#L488

To Reproduce

NODE_OPTIONS='--inspect=0.0.0.0' next dev

Describe the Bug

NodeJS's --inspect switch takes an optional address as a parameter that isn't being honored by Next. Next crashes when that is present.
spec: --inspect[=[host:]port]
https://nodejs.org/api/cli.html#--inspecthostport

In order to be able to expose a debugger from inside a Docker container, it has to listen on 0.0.0.0 instead of the default 127.0.0.1. To do that, we have to specify --inspect=0.0.0.0:9229.

The result of doing this is:

- info the --inspect option was detected, the Next.js proxy server should be inspected at port 0.
- ready started server on 0.0.0.0:3000, url: http://localhost:3000
- info the --inspect option was detected, the Next.js routing server should be inspected at port 1.
/usr/local/bin/node:  must be 0 or in range 1024 to 65535.

This and the root cause has been clearly described earlier in: #47083 but not fixed, as mentioned by gregmartyn in #47083 (comment)

This has also been described in (and presumably fixed but not accepted) in #47671

Expected Behavior

Start node debugger on 0.0.0.0 and default ports 9232 & 9233 instead of parsing "0.0.0.0" as a port only integer.
Honor the node --inspect switch parameters.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

@mkoreo mkoreo added the bug Issue was opened via the bug report template. label Jul 24, 2023
@khuezy
Copy link
Contributor

khuezy commented Jul 27, 2023

I think it's broken in the latest version, even --inspect w/o any arguments fails. It looks like it opens 2 inspector 9229 and 9230 but none of the break points works when you attach on either port.

@HelmerBarcos
Copy link

HelmerBarcos commented Aug 7, 2023

Its is a duplication of #47083. I will create a PR in order to fix this. This should help people debugging an nextjs application that runs inside a docker container

@simonstaton
Copy link

Any update on this? Currently it's impossible to debug a NextJS application running in a docker container.

@hanoii
Copy link

hanoii commented Nov 14, 2023

I used ssh tunnels to work around this

@x-yuri
Copy link

x-yuri commented Dec 1, 2023

I also ran into it while trying to debug nextjs in a docker container. node_module/.bin/next dev starts the dev server here. And before that it amends the node options (to make the child bind to the next port, to be able to debug both processes). The thing is, getDebugPort and the "change the options" code (the previous link) handle only the --${nodeDebugType}=PORT case. But there's also --${nodeDebugType}=HOST:PORT and --${nodeDebugType}=HOST.

Workaround: change this line to:

NODE_OPTIONS = `${NODE_OPTIONS} --${nodeDebugType}=0.0.0.0:9230`;

then:

$ NODE_OPTIONS=--inspect-brk=0.0.0.0 node_modules/.bin/next dev

And another relevant link:

https://github.com/vercel/next.js/blob/v14.0.4-canary.32/packages/next/src/server/lib/start-server.ts#L240-L245

P.S. This must be an anti-reverse-engineering kind of bug :)

@StefanMeindlDatenKraft
Copy link

I tried the fix from x-yuri but its still not working for me (using the node alpine 3.18 img with yarn run dev as start command and NODE_OPTIONS='--inspect=0.0.0.0' next dev for the dev script in the package.json)

Is there any fix comming? Or did I miss something?

@x-yuri
Copy link

x-yuri commented Dec 7, 2023

@StefanMeindlDatenKraft I just confirmed that the workaround works. If it still doesn't for you, I expect a long explanation, as I did.

@StefanMeindlDatenKraft
Copy link

Thanks for the quick reply but still no luck. Here is what I did:

I have a custom image for the node alpine image and I defined the entry point like this:

ENTRYPOINT ["tail"]
CMD ["-f","/dev/null"]

Then I connected to the container using docker exec -it docker_name /bin/sh and in there I followed your steps.

Here is the console output:

~ $ diff -u node_modules/next/dist/cli/next-dev.js.bak node_modules/next/dist/cli/next-dev.js

--- node_modules/next/dist/cli/next-dev.js.bak
+++ node_modules/next/dist/cli/next-dev.js
@@ -222,7 +222,7 @@
                 NODE_OPTIONS = `${NODE_OPTIONS} --max-old-space-size=${Math.floor(totalMemInMB * 0.5)}`;
             }
             if (nodeDebugType) {
-                NODE_OPTIONS = `${NODE_OPTIONS} --${nodeDebugType}=${(0, _utils.getDebugPort)() + 1}`;
+                NODE_OPTIONS = `${NODE_OPTIONS} --${nodeDebugType}=0.0.0.0:9230`;
             }
             child = (0, _child_process.fork)(startServerPath, {
                 stdio: "inherit",

~ $ diff -u node_modules/next/dist/server/lib/start-server.js.bak node_modules/next/dist/server/lib/start-server.js
--- node_modules/next/dist/server/lib/start-server.js.bak
+++ node_modules/next/dist/server/lib/start-server.js
@@ -128,6 +128,7 @@
         throw new Error("Using a self signed certificate is only supported with `next dev`.");
     }
     async function requestListener(req, res) {
+debugger
         try {
             if (handlersPromise) {
                 await handlersPromise;

~ $ NODE_OPTIONS=--inspect=0.0.0.0 node_modules/.bin/next dev

Debugger listening on ws://0.0.0.0:9229/65bad928-9f14-43c7-8be8-f622b6d9a021
For help, see: https://nodejs.org/en/docs/inspector
Debugger listening on ws://0.0.0.0:9230/e1802e6b-ae11-4e34-a96d-c7b644c8a8b3
For help, see: https://nodejs.org/en/docs/inspector
   the --inspect option was detected, the Next.js router server should be inspected at port 0.
   ▲ Next.js 14.0.3
   - Local:        http://localhost:3000

Starting inspector on 0.0.0.0:9230 failed: address already in use
Starting inspector on 0.0.0.0:9230 failed: address already in use
(node:947) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
 ✓ Ready in 2.6s

@StefanMeindlDatenKraft
Copy link

@x-yuri what was your output from next js? Did it also start two debugger for you on 9229 and 9230?

@x-yuri
Copy link

x-yuri commented Dec 7, 2023

@StefanMeindlDatenKraft Yep. node_modules/.bin/next dev forks at least one child. Or to be more precise, 2 children. That's why I get:

Starting inspector on 0.0.0.0:9230 failed: address already in use

later on. For some reason you get 2 such messages. Which means it tries to fork 3 processes. Not sure what it means.

I don't see your debugger connecting to the node processes. Do they appear in chrome://inspect like on the first screenshot? Do you click on "inspect" or "Open dedicated DevTools for Node"? Do you publish the 9229, 9230 ports (to the host)? How do you run the container?

Try to follow the steps in the gist exactly. Does it work with a freshly made nextjs app, not with yours?

You say that it doesn't work. That's not informative at all. What exactly happens? You don't see the node processes in chrome://inspect? The computer reboots? The screen goes blank?

On a side note, I believe sleep infinity makes more sense than tail -f /dev/null.

@StefanMeindlDatenKraft
Copy link

StefanMeindlDatenKraft commented Dec 7, 2023

Yeah that is what I meant, it does not show up in chrome://inspect.

I do have a docker-compose.yml where I expose the app port, 9229 and 9230 and start it with docker-compose up. With my nextjs app I get 2 messages. When i create a fresh one I get just 1 but still with Starting inspector on 0.0.0.0:9230 failed: address already in use. And I followed the steps 1:1.

Btw thanks for the tip @x-yuri with sleep infinity

@x-yuri
Copy link

x-yuri commented Dec 7, 2023

When I do -p 9229:9229 in place of -p 127.0.0.1:9229:9229 the node processes don't show up in chrome://inspect for some reason. UPD 9229:9229 stopped to work since around node 14.21.3 (Alpine Linux 3.14). More on it here.

"address already in use" is expected. My patch makes all children try to use 9230. Only the first one succeeds. Usually that's not a problem. Particularly most likely in your case and in the case in the gist.

For 9230 to work it should be added to the list:


@StefanMeindlDatenKraft
Copy link

So the problem was with the docker configuration, I am still trying to figure out what the difference between my config and the docker run config of yours is, but when I use the docker run ... alpine:3.18 it works and I can inspect.

I will post again when I find the issue. Thanks for your help and quick replies @x-yuri

@StefanMeindlDatenKraft
Copy link

I regret to inform that I am not able to read.

In my docker-compose.yml I had following configuration:

...
-port
    9999:3000
    9230:9230
...

after changing it to 127.0.0.1:9230:9230 it worked

@alessandrojcm
Copy link

alessandrojcm commented Dec 14, 2023

Is there any progress or workaround for this issue? I need to debug an issue that only happens inside a container and I cannot seem to attach the debugger. Passing --inspect=0.0.0.0:9229 makes the container exit with must be 0 or in range 1024 to 65535. Passing only the inspect flag works but it binds to 127.0.0.1. Using Next 14.0.4 and Node 21.

@StefanMeindlDatenKraft
Copy link

StefanMeindlDatenKraft commented Dec 14, 2023

As mentioned in @x-yuri s guide you have to change the sourcecode of next with this command: sed -Ei '/NODE_OPTIONS.*nodeDebugType.*/s//NODE_OPTIONS = `${NODE_OPTIONS} --${nodeDebugType}=0.0.0.0:9230`;/' node_modules/next/dist/cli/next-dev.js /my-app # diff -u node_modules/next/dist/cli/next-dev.js.bak node_modules/next/dist/cli/next-dev.js

@alessandrojcm
Copy link

As mentioned in @x-yuri s guide you have to change the sourcecode of next with this command: sed -Ei '/NODE_OPTIONS.*nodeDebugType.*/s//NODE_OPTIONS = `${NODE_OPTIONS} --${nodeDebugType}=0.0.0.0:9230`;/' node_modules/next/dist/cli/next-dev.js /my-app # diff -u node_modules/next/dist/cli/next-dev.js.bak node_modules/next/dist/cli/next-dev.js

That did it, thanks very much.

@jeroenbegyn
Copy link

Workaround also works for me!

@timmywil
Copy link
Contributor

Worth pointing out that the workaround shows how easy this would be to fix. Let's get the fix in a release.

@sitole
Copy link

sitole commented Apr 17, 2024

Currently still relevant issue.
It's not possible to propagate debugger from Docker container because by default it listens only on internal IP.

timneutkens pushed a commit that referenced this issue Apr 25, 2024
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->

### What?

Previously, parsing and managing the `NODE_OPTIONS` was performed using
a series of regular expressions. These were prone to bugs, and have
already caused a few issues. This moves us over to the standard
`parseArgs`
([docs](https://nodejs.org/docs/latest/api/util.html#utilparseargsconfig)):

```js
import { parseArgs } from "node:utils"
```

### Why?

This simplifies the argument parser dramatically, removing the need for
any special patterns or accommodations. No need to maintain all these
patterns when there's a lightweight built-in parser already available.

Fixes #53127
Fixes #53757
Fixes #47083
Fixes #50489
Closes #60919 
Closes #59410
Closes NEXT-3219
Copy link
Contributor

github-actions bot commented May 9, 2024

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot added the locked label May 9, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 9, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. locked
Projects
None yet
Development

Successfully merging a pull request may close this issue.