644

I have my first node.js app (runs fine locally) - but I am unable to deploy it via heroku (first time w/ heroku as well). The code is below. SO doesn't let me write so much code, so I would just say that the running the code locally as well within my network shows no issue.

 var http = require('http');
 var fs = require('fs');
 var path = require('path');

 http.createServer(function (request, response) {

    console.log('request starting for ');
    console.log(request);

    var filePath = '.' + request.url;
    if (filePath == './')
        filePath = './index.html';

    console.log(filePath);
    var extname = path.extname(filePath);
    var contentType = 'text/html';
    switch (extname) {
        case '.js':
            contentType = 'text/javascript';
            break;
        case '.css':
            contentType = 'text/css';
            break;
    }

    path.exists(filePath, function(exists) {

        if (exists) {
            fs.readFile(filePath, function(error, content) {
                if (error) {
                    response.writeHead(500);
                    response.end();
                }
                else {
                    response.writeHead(200, { 'Content-Type': contentType });
                    response.end(content, 'utf-8');
                }
            });
        }
        else {
            response.writeHead(404);
            response.end();
        }
    });

 }).listen(5000);

 console.log('Server running at http://127.0.0.1:5000/');

Any idea ?

user428900
  • 7,091
  • 6
  • 23
  • 18

39 Answers39

1383

Heroku dynamically assigns your app a port, so you can't set the port to a fixed number. Heroku adds the port to the env, so you can pull it from there. Switch your listen to this:

.listen(process.env.PORT || 5000)

That way it'll still listen to port 5000 when you test locally, but it will also work on Heroku. Important note - PORT word must be capital.

You can check out the Heroku docs on Node.js here.

silpol
  • 347
  • 1
  • 10
  • 29
redhotvengeance
  • 27,446
  • 10
  • 49
  • 54
  • 187
    important that you use process.env.PORT and not process.env.port. – gprasant Feb 25 '14 at 14:15
  • 3
    Here's an example: https://github.com/heroku/node-js-getting-started/blob/master/index.js – Pablo Apr 28 '16 at 11:39
  • Also, _do no_ attempt to set the port as an environment variable with `heorku config:set PORT=...` as _that is doomed to fail_. Other environment variables can be set this way, but the `PORT` is not surprisingly unsupported (if only I RTFM first). – Boaz Jun 05 '18 at 08:34
  • So, need use `.listen(process.env.PORT || 5000)`, don't use `.listen(process.env.NODE_PORT || 5000)`. – Dmitry S. Nov 13 '18 at 19:07
  • Brilliant, this was key: "Heroku dynamically assigns your app a port, so you can't set the port to a fixed number." hard-coding the port was ruining me. – Josh Feb 06 '20 at 10:10
  • 11
    You'll also need to make sure the host is set to `0.0.0.0` – Ishan Madhusanka Oct 31 '20 at 06:19
  • For most people, process.env.PORT will solve the issue. For me fixing Heroku environment variables did the trick(Postgres db url was wrong). In logs it did not show that it could not connect to Postgres, and it would try connecting for more than 60 sec and resulted in this error. I used those prod env variables in localhost and there got the error in console. – Rahul Jain Apr 17 '21 at 20:44
  • 3
    Do ensure that you have `process.env.PORT || 5000` and not `5000 || process.env.PORT`. Spent quite some time before realizing my silly mistake... – get_php_workin Aug 19 '21 at 15:45
88

It's worth mentioning that if your code doesn't specify a port, then it shouldn't be a web process and probably should be a worker process instead.

So, change your Procfile to read (with your specific command filled in):

worker: YOUR_COMMAND

and then also run on CLI:

heroku scale worker=1
double-beep
  • 5,031
  • 17
  • 33
  • 41
zthomas.nc
  • 3,689
  • 8
  • 35
  • 49
  • 2
    I had same issue I could resolved issue with replace 'localhost' with IP which is '0.0.0.0' – Damith Asanka Jul 16 '17 at 18:54
  • 8
    I'm running a Discord bot on Heroku, and this threw me for a loop. Slack, Hipchat, etc. bots could likely have similar issues. – Skylar Aug 29 '17 at 04:12
  • 3
    If you go this route, make sure to go to the Resources tab, turn off the web process and turn on the worker process. That way Heroku won't expect a port binding. – Isaac Lyman Sep 28 '18 at 16:29
  • 1
    Ohh thank you so much. I went nuts trying to look this up. I had no idea web and worker applications differed in Heroku in terms of the Procfile. It is worth mentioning that they needed me to add a `start` script in my `package.json` – Rishav Mar 06 '19 at 16:19
  • 3
    In my case i changed the procfile from web to worker. It worked!! Thkns – rodrigorf Nov 13 '19 at 15:26
  • @IsaacLyman Thank you, this was very helpful for me. My app is now a worker, but I only want it to run once a day via the Heroku Scheduler (which I have set up). However, I've noticed that it's continuously running. Is there a way to specify that it *only* runs once a day? – mpc75 Jan 17 '20 at 15:44
  • This helped me too as I wasn't running a server but rather just a node script on heroku – Ayudh Aug 17 '22 at 16:30
60

For those that are passing both a port and a host, keep in mind that Heroku will not bind to localhost.

You must pass 0.0.0.0 for host.

Even if you're using the correct port. We had to make this adjustment:

# port (as described above) and host are both wrong
const host = 'localhost';
const port = 3000;

# use alternate localhost and the port Heroku assigns to $PORT
const host = '0.0.0.0';
const port = process.env.PORT || 3000;

Then you can start the server, as usual:

app.listen(port, host, function() {
  console.log("Server started.......");
});

You can see more details here: https://help.heroku.com/P1AVPANS/why-is-my-node-js-app-crashing-with-an-r10-error

gregb
  • 732
  • 5
  • 9
  • 7
    This answer is not only more complete, but the only one that targeted the two possible problems. In my case the port configuration was correct, but not the listening address. This should be the accepted answer. – Danielo515 Feb 12 '18 at 06:11
  • In my case it works as I changes as below `const port = 3000;` to `const port = process.env.PORT || 3000;` it works on heroku – vpgodara Jan 06 '19 at 04:42
  • 3
    Omg, I can't believe how this is isn't mentioned anywhere in the docs. I even tried to let Heroku pass their own `process.env.HOST` but that didn't work as well. At first I was setting it as localhost thinking that Heroku sets up some sort of a reverse proxy. Not only this isn't documented, but the answer had to be the fourth one on Stackoverflow. Sometimes I wonder why I chose this career path :( – Charming Robot Jul 23 '20 at 20:12
  • THANK YOU!!! it would be great if this was FRONT AND CENTER in the heroku docs – Adam Woolhether Feb 24 '22 at 01:50
58

The error happens when Heroku failed to bind the port or hostname at server.listen(port, [host], [backlog], [callback]).

What Heroku requires is .listen(process.env.PORT) or .listen(process.env.PORT, '0.0.0.0')

So more generically, to support other environments, use this:

var server_port = process.env.YOUR_PORT || process.env.PORT || 80;
var server_host = process.env.YOUR_HOST || '0.0.0.0';
server.listen(server_port, server_host, function() {
    console.log('Listening on port %d', server_port);
});
Royce Lee
  • 581
  • 4
  • 2
  • 9
    With following call: app.listen(serverPort, "localhost", function (err) { Heroku was failing. Switching "localhost" to "0.0.0.0" helped. Thanks! – pubsy Aug 29 '17 at 21:02
29

I had same issue while using yeoman's angular-fullstack generated project and removing the IP parameter worked for me.

I replaced this code

server.listen(config.port, config.ip, function () {
  console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});

with

server.listen(config.port, function () {
  console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});
vinesh
  • 4,745
  • 6
  • 41
  • 45
12

In my case, I was using example from https://hapijs.com/

To fix the problem I replaced

server.connection({ 
    host: 'localhost', 
    port: 8000 
});

with

server.connection({
    port: process.env.PORT || 3000 
});
nexuzzz
  • 238
  • 3
  • 7
  • and for those of use specifying `process.env.PORT` correctly, but leaving in the `host` param: you can't :) see here: https://stackoverflow.com/a/34956330/626369 – Dominick May 27 '17 at 02:55
12

change this line

app.listen(port);

to

app.listen(process.env.PORT, '0.0.0.0');

it will work

Dilan
  • 2,610
  • 7
  • 23
  • 33
Nishant Yadav
  • 199
  • 2
  • 5
10

While most of the answers here are valid, for me the issue was that I was running long processes as part of npm run start which caused the timeout.

I found the solution here and to summarize it, I just had to move npm run build to a postinstall task.

In other words, I changed this:

"start": "npm run build && node server.js"

to this:

"postinstall": "npm run build",
"start": "node server.js"

Come to think of this, it totally makes sense because this error (which used to appear occasionally) was becoming more and more common as my app kept growing.

Georgios
  • 4,764
  • 35
  • 48
6

Changing my listening port from 3000 to (process.env.PORT || 5000) solved the problem.

double-beep
  • 5,031
  • 17
  • 33
  • 41
Akshata Dabade
  • 477
  • 5
  • 10
4

Restarting all dynos in heroku did the trick for me

enter image description here

Muhammad Awais
  • 1,608
  • 1
  • 21
  • 21
3

In my case, I was using Babel with the babel-plugin-transform-inline-environment-variables plugin. Apparently, Heroku does not set the PORT env variable when doing a deployment, so process.env.PORT will be replaced by undefined, and your code will fallback to the development port which Heroku does not know anything about.

Edgar Ortega
  • 1,672
  • 18
  • 22
3

I had the same issue because I didn't define Procfile. Commit a text file to your app's root directory that is named Procfile without a file extension. This file tells Heroku which command(s) to run to start your app.

web: node app.js
Joshua Varghese
  • 5,082
  • 1
  • 13
  • 34
AmirRezaM75
  • 1,030
  • 14
  • 17
3

I Use ReactJs, If you want upload to heroku add this in your webpack.config.js

Because if not add you will have error

Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

//webpack.config.js add code like that

const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
var server_port = process.env.YOUR_PORT || process.env.PORT || 5000;
var server_host = process.env.YOUR_HOST || "0.0.0.0";

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"]
      }
    ]
  },
  devServer: {
    disableHostCheck: true,
    contentBase: "./ dist",
    compress: true,
    inline: true,
    port: server_port,
    host: server_host

  },
  plugins: [
    new HtmlWebPackPlugin({
      template: "./src/index.html",
      filename: "index.html"
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  ]
};
Anurag Hazra
  • 403
  • 1
  • 6
  • 14
NUR CHULIS
  • 31
  • 3
3

I realized that I don't need the port number in the request endpoint, so the endpoint was herokuapp.com and not herokuapp.com:5000.

The listen() call can be without host and callback:

server.listen(5000);
double-beep
  • 5,031
  • 17
  • 33
  • 41
2

Edit package.json:

...
"engines": {
"node": "5.0.0",
"npm": "4.6.1"
},
...

and Server.js:

...
var port = process.env.PORT || 3000;
app.listen(port, "0.0.0.0", function() {
console.log("Listening on Port 3000");
});
...
double-beep
  • 5,031
  • 17
  • 33
  • 41
Naveen Kumar V
  • 2,559
  • 2
  • 29
  • 43
  • In my case I took out that part of the `package.json`. I believe updating it should also solve this problem. – Mark Jan 17 '18 at 19:06
2

I've spent a lot of hours to find the root cause, and eventually I've found that this timeout (60s) can be adjustable. Here you may change 60 second to 120 or even more. It works for me, hope will help anybody else!

Ruslan Valeev
  • 1,529
  • 13
  • 24
2

To resolve this follow these Four simple steps: in the package.json file:

1- set the main field to the server file:

"main": "server.js" // <-- here set you server file

2- add the host parameter to the app.listen function

const port = process.env.PORT || 3000;
const host = '0.0.0.0'
app.listen(port, host, ()=> connsole.log(`server is running on port ${port}`)

3- add the postinstall script to package.json file

"scripts": {
     "postinstall": "npm run build", // <-- add this line
     "start": "node server.js" // <-- change server.js to you main file
}

4- add the engines field in package.json file

"engines": {
   "node": ">=14.0.O", // <-- change it to your node version. you can "node -v" in you command line
   "npm": ">=7.7.0" // <-- change this to your npm version. you can use "npm -v" in the command line to get your npm version
}

let me know if you have any succes with this!

MR X
  • 21
  • 1
2

Use process.env.PORT || 3000 for your port.

This will use Heroku's port when available or use port 3000 if it's not available (for example, local testing)

You can change 3000 to whatever you want, for example 8080

Coder Gautam YT
  • 1,044
  • 7
  • 20
  • 1
    In my scenario, I got the same error. However, my server.js file had only 3000 as the port. But once I have added the port for the Heroku which is process.env.PORT, I was able to properly deploy the app. Thanks. – VOSH Oct 23 '21 at 10:19
2

In your package.json file, in the scripts, make sure your start script contains -p $PORT.

Example of package.json (in this case, for NextJS app):

{
  "private": true,
  "scripts": {
    "dev": "next dev -p 3001",
    "build": "next build",
    "start": "next start -p $PORT" // make sure to have -p $PORT in here
  },
  "dependencies": {
    "typescript": "^4.3.2"
  },
  "devDependencies": {
    "@next/eslint-plugin-next": "^11.1.2",
    "@types/mongoose": "^5.11.97"
    "typescript": "^4.3.2"
  }
  "license": "MIT"
}

Gabriel Arghire
  • 1,992
  • 1
  • 21
  • 34
1

I had same issue I could resolved issue with replace 'localhost' with IP which is '0.0.0.0'

Damith Asanka
  • 934
  • 10
  • 12
1

In my case, neither the port nor the host was the problem. The index.js was divided into 2 files. server.js:

//server.js
const express = require('express')
const path = require('path')

const app = express()

app.use(express.static(path.resolve(__dirname, 'public')));
// and all the other stuff
module.exports = app

//app.js
const app = require('./server');
const port = process.env.PORT || 3000;
app.listen(port, '0.0.0.0', () => {
    console.log('Server is running s on port: ' + port)
});

from package.json we ran node app.js.

Apparently that was the problem. Once I combined the two into one file, the Heroku app deployed as expected.

double-beep
  • 5,031
  • 17
  • 33
  • 41
jonyB
  • 9,257
  • 2
  • 8
  • 11
1

I have the same issue but my environment variables are set well and the version of npm and node is specified in package.json. I figured out it is because, in my case, Heroku needs "start" to be specified in package.json:

  "scripts": {
    "start": "node index.js"
  }

After adding this to my package.json my node app is successfully deployed on Heroku.

1

While developing the application we need to define the PORT in the following way:

const port = process.env.PORT || 4000; // PORT must be in caps

And while deploying the app to server add the following method:

app.listen(port, () => {
 console.info("Server started listening.");
});

We can pass hostname as second parameter while running it in local. But while deploying it to server the hostname parameter should be removed.

app.listen(port, hostName, () => {
  console.info(`Server listening at http://${hostName}:${port}`);
});
Suman Das
  • 11
  • 5
1

My case was that I was running Database scripts on start up and were taking long time. I solved this by manually running npm start after deployment is complete.

Fine Boy
  • 321
  • 4
  • 6
1

I was working with a Vue app using vite when I ran into this issue. My npm run start command was defined as:

"scripts": {
  "start": "vite --port 8080",
}

The explanation has been overdue on this answer thread but I just thought to provide the syntax of the solution in case anybody else is looking for it:

"start": "vite --host '0.0.0.0' --port $PORT",
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
mau
  • 21
  • 4
0

A fixed number can't be set for port, heroku assigns it dynamically using process.env.PORT. But you can add them both, like this process.env.PORT || 5000. Heroku will use the first one, and your localhost will use the second one.

You can even add your call back function. Look at the code below

app.listen(process.env.PORT || 5000, function() {
    console.log("Server started.......");
});
Aminu Kano
  • 2,595
  • 1
  • 24
  • 26
0

At of all the solution i have tried no one work as expected, i study heroku by default the .env File should maintain the convention PORT, the process.env.PORT, heroku by default will look for the Keyword PORT.

Cancel any renaming such as APP_PORT= instead use PORT= in your env file.

Codedreamer
  • 1,552
  • 15
  • 13
0

From the heroku bash process, pass down the value of $PORT to your node app using an options parser like yargs.

Here is an example of how you might do that. On the scripts object, inside package.json, add a start method "node server --port $PORT".

In your server file, use yargs to get the value from the port option (--port $PORT) of the start method:

const argv = require('yargs').argv;
const app = require('express')();

const port = argv.port || 8081;

app.listen(argv.port, ()=>{
    console.log('Probably listening to heroku $PORT now ', argv.port); // unless $PORT is undefined, in which case you're listening to 8081.
});

Now when your app starts, it will bind to the dynamically set value of $PORT.

Aori Nevo
  • 71
  • 6
0

If, like me, you're configuring Heroku to run a script from your package.json file on deploy, make sure you haven't hard-coded the value of PORT in that script! If you do, you'll end up like me and spend an hour trying to figure out why you're getting this error.

Chris
  • 9,994
  • 3
  • 29
  • 31
0

I had same issue but with express and apollo-server. The solution from here:

The only special consideration that needs to be made is to allow heroku to choose the port that the server is deployed to. Otherwise, there may be errors, such as a request timeout.

To configure apollo-server to use a port defined by Heroku at runtime, the listen function in your setup file can be called with a port defined by the PORT environment variable:

> server.listen({ port: process.env.PORT || 4000 }).then(({ url }) => { 
> console.log(`Server ready at ${url}`); });
scopchanov
  • 7,966
  • 10
  • 40
  • 68
0

In my case I had two issues...

1) no listener at all because of running app from another entry file and this run script was deleted from package.json "scripts"

enter image description here

2) Case sensitive problem with 'Sequelize' instead of 'sequelize'

enter image description here

Elmatsidis Paul
  • 385
  • 1
  • 7
  • 19
0

My problem was that when deploying to heroku I got an error:

Web process failed to bind to $PORT within 60 seconds of launch

when running heroku logs --tail in the terminal. BUT the application would run as expected when I ran the server locally.

I had this in my index.js file (server file)

const PORT = process.env.port || 4000

app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`)
})

But should have had this

const PORT = process.env.PORT || 4000

app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`)
})

Use process.env.PORT, not process.env.port, because port is not the same as PORT obviously.

Credit to gprasant.

double-beep
  • 5,031
  • 17
  • 33
  • 41
0

I will recommend you read the log very well in order to easily troubleshoot it. if you are referencing a PORT as an environment variable (env) make sure it is PORT not port because heroku automatically assigns a PORT number to your application when you deploy it. process.env.PORT not process.env.port

0

this is also a good way.to solve the error

  const PORT = process.env.PORT || 3000                                                   
   app.listen(                                                                                 
    PORT,                                                                                                    
    '0.0.0.0',                                                                                
    function () {                                                                                                             
    console.log("Server started.......");                                                              
    }                                                                                                                   
  );
0

If you are getting this error and the above did not work, the error is not from the R10 itself.the error is caused by R14 (Memory quota exceeded) and this is because a part of your code uses multer (multer.diskStorage() method) or some other library for storing images or other files using some form of local storage. the delay caused by error R14 then leads to the R10 (Boot timeout) error.

solution:

in your package.json file, change your start to "start" : "node --max-old-space-size=4096 server/index.js". this increases storage size.

also

set this heroku variable heroku canfig:set NODE_ENV=dev

Michael I.
  • 9
  • 1
  • 4
0

For me, the problem was capitalization. You know, after hours of coding, your eyes miss some little details.

In my code, I had process.env.port instead of process.env.PORT, so watch out, the PORT environment variable must be uppercased.

See the example below:

const PORT = process.env.PORT || 3000;
const HOST = process.env.HOST || '0.0.0.0';

const express = require('express');
const app = express();

app.listen(PORT, HOST, () => {
      console.log('Server started on ' + HOST + ':' + PORT);
})
David Corral
  • 4,085
  • 3
  • 26
  • 34
  • @RohanDevaki I've updated my answer with a proper code example, without typos. Have a nice day! – David Corral Oct 16 '21 at 12:22
  • lol , after my answer? – Rohan Devaki Oct 16 '21 at 12:34
  • @RohanDevaki you asked me to improve my answer with a (useless) piece of code, so I did it. Your answer is not providing anything that I haven't already provided yet. – David Corral Oct 16 '21 at 12:45
  • it was providing, you have made it similar now – Rohan Devaki Oct 16 '21 at 14:46
  • @RohanDevaki you answer still is incomplete, not properly explained, and have several typos. You would make yourself a favour by removing it, accepting that you are wrong and you tried to copy my answer. I've already flag it so a moderator can solve the issue. Not going to waste a single minute more in this discussion. Have a nice day! – David Corral Oct 16 '21 at 15:17
  • i have already flagged your answer , because of the code example which you didnt give , it wasn't working for me , that is why you have written a new answer , there are no typos and i have explained everything in the answer , i too dont want to discuss with you anymore. – Rohan Devaki Oct 17 '21 at 03:20
0

I wasted a full day thinking the backend had the problem. After going through all the solutions here for and a thorough log inspection, realized it was the frontend react App.js that had the problem.

I changed each

Axios.post(`${process.env.REACT_APP_BASE_URL}/createOrder`, {

})

to

Axios.post(`/createOrder`, {

})

and it worked!

Apparently react files had nothing to do with heroku deployment!

Upulie Han
  • 431
  • 1
  • 7
  • 15
0
  • From the backend side we don't need to assign port.if you are using PORT variable just remove it.
  • Heroku will automatically assign port to process.env.PORT.
  • Make sure PORT word is in capital.
  • You can make below changes. this may solve your problem.
  • After deployment you can see(in logs) every time heroku will assign new port.
const PORT = process.env.PORT || 8080;
    httpServer.listen(PORT, () => console.log(`--- Spinning on ${PORT} with ${process.env.NODE_ENV} environment  ---`));

0

I had a similar issue trying to solve it for hours (H10 GET=/). I tried changing PORT but with no results. Turns out the solution was simple. I changed one line in my package.json file. From nodemon to node and it worked:

"scripts": {
"start": "nodemon app.js"

To:

 "scripts": {
 "start": "node app.js"
Nibelur
  • 27
  • 7