502 Bad Gateway means nginx, the web server in front of your site, asked your app for the page and got no usable answer. The app is not running, not listening where nginx looks, or it crashed mid-request. It is most common on Node.js apps, right after a deploy, a version switch or a new start command.
Why it happens
A Node.js app runs as a service of its own. nginx passes every request it cannot serve from public/ to your app on the port in the PORT environment variable. A 502 follows when:
- The app listens on the wrong port. It listens on a fixed port, like
3000or8080, instead ofprocess.env.PORT. - The start command is wrong. It points at a file the build did not produce, for example
node buildwhen the output is somewhere else. - The app crashes on start. A dependency it needs at runtime sits in
devDependencies(we install production dependencies only), or a required environment variable is missing. The service manager restarts a crashed app a few times in quick succession, then gives up. The app stays down until the next deploy, restart or switch. - The app ran out of memory and was stopped. See "Allowed memory size exhausted" / out of memory.
- On a PHP site: PHP itself is not running, for example straight after a PHP version switch that did not finish.
Note: Every deploy checks your site right after the switch. A Node.js app must start and answer on its port, and the site must answer without a server error such as a 502. If it does not, the deploy fails at Checking the site after the switch and, when there is an earlier release, your site goes back to it. With no earlier release to go back to, the new code stays live and its row in Recent deploys reads live, failing. The check is one moment, though. An app that crashes a minute later, or only on some pages, still passes, so open the site yourself after each deploy.
Fix it
- Read the app's own output. Open Sites, choose your site, then Logs → Application. For a Node.js app, this is everything your app printed to the console, including the crash. Look for
Error: Cannot find module …,EADDRINUSE, or a stack trace from your start-up code. - Check what nginx saw. In Logs → Web server errors,
connect() failed (111: Connection refused) while connecting to upstreammeans nothing was listening.upstream prematurely closed connectionmeans the app crashed while answering. - Put the last good release back while you fix it. If the deploy failed at Checking the site after the switch and says it switched your site back, this is already done. Otherwise, on the Deploys tab, use Roll back to … on the Live now strip. Your files return to the previous release and your database stays as it is. See Approve a release, discard it or roll back.
- Check the port. Your app must listen on
process.env.PORT. In your app (Express):app.listen(process.env.PORT || 3000). - Check the start command. Under Configure → Node.js → Start command, an empty field runs
npm start(ornode server.js/node index.js). Nuxt needsnode .output/server/index.mjs. SvelteKit needsnode build. Press Save; your app restarts with it within a minute. Node.js apps lists the commands per framework. - Check dependencies. Anything your app
requires orimports at runtime must be independencies, notdevDependencies. Commit an up-to-datepackage-lock.json. - Start it again. After a fix that needs no new code (an environment variable, say), press Install & restart in the Deploys tab's side panel. It installs production dependencies and restarts your app. For a fix in your code, push and deploy again.
On a PHP site, open Configure → PHP version, choose the version under Run on and press Switch again. Wait for Now running PHP ….
Still stuck?
If Application is empty and Web server errors shows refused connections, your app never started at all. Contact us with the site name and the time of the deploy, and we will look at the service on our side.