Cannot run React app and tunnel on the same port anymore

I am having a mini app with functions and Custom UI. A few months ago, I was able to ‘npm start’ on port 4000 my frontend app created by ‘create-react-app’ framework, and start ‘forge tunnel’ (configured also on port 4000 in the manifest file). After doing this, I was able to do changes in the frontend code and immediately see the effect in the browser. In one word, the setup worked as expected.

Recently, I changed my laptop (moved to Mac) and reinstalled everything from scratch. Now, when I run the tunnel and then start the React app, I get the following error:

Something is already running on port 4000.

Would you like to run the app on another port instead? › (Y/n)

Interestingly enough, if I run the React app first and then I start the tunnel, everything seems to look fine (no errors/warnings in the tunnel console log), however when I check the app in the browser, it says:

Cannot GET /

Does anyone have an idea what could be the problem?

Can someone shed a light what changes are needed after migrating to Cloudflare tunneling with the latest Forge CLI?

Welcome to the Atlassian developer community @zlatko99,

I’m not aware of any steps necessary to migrate. I’ve been able to switch from ngrok to Cloudflare without any problems. That said, my apps tend to be trivial sample apps.

Focusing on your error, Something is already running on port 4000, maybe check what is running on port 4000 with lsof -i tcp:4000.

Thanks for your response, @ibuchanan.

When I run lsof -i tcp:4000, I get:

? Something is already running on port 4000. Probably:
  node /Users/my_user/.nvm/versions/node/v18.20.4/bin/forge tunnel (pid 2448)
  in /Users/my_user/my_project

Would you like to run the app on another port instead? › (Y/n)

It seems Forge Tunnel is blocking the port on which the React app wants to start. Here is the Manifest snippet related to this:

resources:
  - key: main
    path: static/my_project/build
    tunnel:
      port: 4000

I have set the React to start on port 4000, too.

@zlatko99,

Is there a reason you’re trying to specify the Forge Tunnel port as 4000? I don’t specify the port in my Manifest, and Forge Tunnel seems to figure it out fine. Conversely, is there a reason to specify React run on port 4000?

I don’t think it’s the cause, but from other topics, there seems to be a bug with Node 18 that can affect some people when trying to run forge tunnel. The standard fix seems to be bumping up to Node 20.

@ibuchanan I have tried setting Node 20 before (this is what I run locally anyway), but when forge deploy I am getting:

Error: Manifest validation failed: The value of the name option must be one of: sandbox, nodejs18.x

I set React and Tunnel on port 4000, since I have other apps (not related to Forge) on my Mac running on the default 3000. This setup was working fine with Ngrok, though.

@zlatko99,

I don’t really know how this would have worked before. React and the tunnel should be on different ports. That would have been true for ngrok too. Perhaps ngrok was better at reassigning itself? In any case, please change one of those values (not both) to a free port and I think that should work.

Meanwhile, what I meant was to run Node 20 locally, but not setting that in the manifest. As the error message indicates, the Node runtime on Atlassian will be 18.

@ibuchanan Thanks a lot for the advice to get rid of the port definition! That fixed the problem and the manifest part looks like this now:

resources:
  - key: main
    path: static/my_project/build

No matter what port I run React on, it works fine.

(My understanding is that for Ngrok, the port definition in the manifest was telling it to which port to delegate the requests coming over the network, not that Ngrok and React would run on the same port; of course, that’s not possible.)

1 Like

@ibuchanan Unfortunately, my quick confirmation about the solution was wrong. Yes, the proposed hint made me run the project successfully, but instead of picking up the realtime changes, it served the content from static/my_project/build folder.

As I noticed in the documentation:

To connect a server to forge tunnel, first identify the port that the server is hosted on. In the above example, the port would be 3000. Then, add the following to your manifest.yml file, under the resource your server is hosting:

tunnel:
  port: <YOUR_PORT_HERE>

For example, a resources definition might look like this:

resources:
  - key: main
    path: static/hello-world/build
    tunnel:
      port: 3000

If no port is specified in manifest.yml, the build content is served. If a port is specified, it’s supposed to delegate all the requests to the running React app on that port, as the forge tunnel log suggests:

Listening for requests...

Received proxy request. Serving file index.html for resource main from specified address http://localhost:4000

It all makes sense up to the point when the React app should be run on the specified port. I wouldn’t expect the port to be taken for listening from the tunnel. I am still stuck with this problem. Any other suggestions, please?

After a deeper investigation, I solved the problem. Not sure if this is the most optimal solution, but at least it works for me with React app created with create-react-app tool.

What I have noticed is that when forge tunnel is ran, it binds to [::1]:4000 port (IPv6) version. When I run the React app, it binds to 127.0.0.1:4000 port (IPv4).

I read somewhere on the internet that Webpack dev server doesn’t recognize IPv6 requests, so I ran the React app on [::1]:4000, too. Here, one confusing thing is that two apps can run on the same port at the same time. Howevere, when I do lsof -i tcp:4000, it logs the two processes bound to the same port. One of them on localhost and the other one on *. It seems that these two are different network interfaces and they are considered separate binding contexts.

Also, the order of running is important: first the React app, then the forge tunnel.

According to the docs, I need to have the tunnel → port defined in the manifest.yml. Otherwise the build folder is served.

One thing that I still need to do manually after each and every change is refresh the page in the browser. As I remember in the past with Ngrok, the browser was reloading the changes immediately on saving.

1 Like