Troubleshooting Node.js Deploys
Last updated January 12, 2021
Table of Contents
Your Node.js deploy failed - now what? Start with these simple steps to troubleshoot a build issue.
Check the buildpack
Is the app using the officially supported and maintained buildpack? Most of the time, the standard buildpack is the best choice - either alone, or paired with other buildpacks (such as the Heroku Ruby Buildpack).
To find out, run:
$ heroku buildpacks
To use the official buildpack, run:
$ heroku buildpacks:set heroku/nodejs
Compare Node and npm Versions
The production environment should mirror the app’s development environment as closely as possible. (Being a few patch versions off is okay.) First, check local versions:
$ node --version $ npm --version
Then, compare the results with the
engines section. Make sure a Node version is specified.
Heroku will output which binaries (ie.
npm) are used for each deploy in the build logs:
remote: -----> Installing binaries remote: Resolving node version 12.x... remote: Downloading and installing node 12.16.3... remote: Using default npm version: 6.14.4
The binaries should match up with the same local versions. If they don’t, specify the matching versions in the
Make sure the lockfile is up to date
If a lockfile is present (ie.
yarn.lock) checked into the app’s repository, make sure that the lockfile is both up to date and that the changes are checked into git.
It’s recommended to use a lockfile when third-party dependencies are referenced in the package.json
In order to update the
npm install and check in the changes to the file to git.
To update the
yarn.lock file, run
yarn install and check the changes into git.
Don’t check in generated directories
node_modules directory is generated at build time from the dependencies listed in
package.json and the lockfile. Therefore,
node_modules (and other generated directories like
bower_components) shouldn’t be included in source control. Check with the following:
$ git ls-files | grep node_modules
If there are results, then instruct git to stop tracking
$ echo "node_modules" >> .gitignore $ git rm -r --cached node_modules $ git commit -am 'untracked node_modules'
Check for differences between development and production
Many Node applications have checks that will perform different logic based on the value of the
Occasionally, this can lead to subtle bugs that will only show up when trying to deploy. If a new bug appears while deploying, check to see if it can be reproduced locally by setting
$ NODE_ENV=production npm start
A required file may exist locally, but it’s possible to accidentally prevent it from being included in the app’s git repo by an overly broad rule in
As an example, it may be better to exclude a
lib directory at the root of your application, but with the following:
git will recursively match any subdirectory named
lib, so the file
js/library-name/lib/index.js would not be included in the git repo. Fix this case by moving the slash to the front, which will only match the
lib directory in the application root directory.
Open a ticket
If none of these solutions work to fix the app in question, open a ticket with Heroku so we can help.
AWS Proxy Error
If builds are not completing with an error when downloading Node, there may be an issue downloading binaries. The build error may look like following:
-----> Installing binaries engines.node (package.json): 10 engines.npm (package.json): unspecified (use default) Resolving node version 10... Error: Unknown error installing "10" of node
Or the error may mention this:
-----> Node.js app detected curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to lang-common.s3.amazonaws.com:443
HTTPS_PROXY environment variables in the app’s build will cause these types of failures. If the build or app does not need
HTTPS_PROXY environment variables, it’s recommended to remove the variables from the app’s environment.
$ heroku config:unset HTTP_PROXY HTTPS_PROXY
If the build environment does require a proxy to be used for HTTP or HTTPS connections, set the
NO_PROXY environment variable to
amazonaws.com. This can be done by setting this in the environment (ie.
export NO_PROXY=amazonaws.com) before executing the Node process, or setting the environment variable:
$ heroku config:set NO_PROXY=amazonaws.com
If a module that is included in the
package.json is missing from the build or the production app, it may have been removed by Heroku during pruning. A common error would look something like this:
internal/modules/cjs/loader.js:960 throw err; ^ Error: Cannot find module 'express'
In order create a smaller slug size for apps, the buildpack will prune out the
devDependencies from the
package.json at the end of the build, so that the slug will only include the
dependencies that are listed at runtime. If there is a dependency that is in the
devDependencies that is needed after the prune occurs, move the dependency to
dependencies, so it is not removed.
The other solution is to turn off pruning of
devDependencies altogether. To do this, set the following for npm:
$ heroku config:set NPM_CONFIG_PRODUCTION=false
If the app is using Yarn, run the following:
$ heroku config:set YARN_PRODUCTION=false
For more information about configuration package installations, visit the Node.js Support docs.
Incorrect Port Setup
Heroku apps will not bind to just any port that your app is set up with. Apps should use the Node
process to bind to a port.
When set up incorrectly, your app will deploy successfully, but the app will crash repeatedly. You may see an error like this in your logs:
heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" status=503 bytes= protocol=https
To fix this, use the
process.env.PORT variable to bind your web server to the port. If you’re using port 3000 for your local development, your code should look something like this:
app.listen(process.env.PORT || 3000);
The Node process will take the
PORT environment variable that has been set by Heroku in your app.
Install and Build Script Failures
Sometimes installing a dependency or running a build locally completes successfully, and when it gets to Heroku, the build will fail. If you run into an issue where a dependency only fails on Heroku, it’s recommended to spin up a one-off dyno to debug the script. The dyno will be created from the slug of the most recent deploy, so try to get the build to pass in order to debug in a Heroku environment - you can do this by uninstall the troublesome dependency, removing the build script from the
package.json, or making other modifications to the code to make the build pass.
Once you’ve deployed the code to a staging app, create the one-off dyno:
heroku run bash -a $APP_NAME Running bash on ⬢ app-name... up, run.2524 (Hobby) $
After the dyno has spun up, you can poke around and run scripts to debug. Install dependencies as needed to poke around the dyno:
$ npm install debug up to date, audited 52 packages in 2s found 0 vulnerabilities
package.json, you’ll see that
debug has been installed. You may also have a failing build script - it can be run it manually with the
$ npm run build-production --verbose