Blog

502 Bad Gateway in nginx: what it means and how to fix it

3 min read ยท published 2026-10-13

What the error means

A 502 from nginx says: I am up, I passed the request to your app, and what came back was nothing or nonsense. The problem is almost always behind nginx: the app process, its port or its socket. A visitor cannot fix it. If the app had answered too slowly instead, you would see a 504.

Read the error log first

Run sudo tail -n 50 /var/log/nginx/error.log and find the line with upstream in it. It names the cause.

The log line containsCauseFix
connect() failed (111: Connection refused)The app is not running, or it listens on another portStart the app. Compare the port in proxy_pass with the one the app binds
failed (2: No such file or directory)nginx and the app name different socket paths, or the app never created the socketUse one socket path in both configs, then restart the app
failed (13: Permission denied)nginx may not open the socket, or SELinux blocks the connectionGive the nginx user access to the socket. On SELinux: setsebool -P httpd_can_network_connect 1
upstream prematurely closed connectionThe app crashed or was killed in the middle of the requestRead the app's own log. Check for the out-of-memory killer: dmesg -T | grep -i oom
upstream sent too big headerThe response headers, usually cookies, are larger than the bufferRaise proxy_buffer_size, or fastcgi_buffer_size for PHP
no live upstreamsEvery server in the upstream block has failedFix the backends. The lines above this one say why each of them failed

If the log is not clear, check in this order

  1. Is the app alive? systemctl status your-app, or docker ps. If it restarted a minute ago, its own log has the reason.
  2. Does it answer locally? On the server run curl -I http://127.0.0.1:3000 with your app's port. No answer means the app is the problem and nginx is only the messenger.
  3. Does nginx point at it? The address in proxy_pass or fastcgi_pass has to match what the app listens on, character for character.
  4. After any config change: sudo nginx -t && sudo systemctl reload nginx.

Find out before a customer does

A 502 that lasts two minutes at 3 a.m. leaves no trace unless something outside was watching. An outside check is that something.

  1. Open upcontrol.io, type your domain, and add a check for the URL that matters most, for example the checkout page.
  2. After three failed checks in a row an incident opens, titled with the cause, such as "Checkout returning 502". The alert goes to Telegram, Slack, Discord or email.
  3. Run npx upcontrol in your repo and let your coding agent wire the logs. The incident page then carries the app's log lines and the deploy around the failure, which is usually the answer to why.
The add monitor form with the Website kind selected and https://tidvatten.app/checkout in the URL field
Adding a website check: the URL, an optional text the page must contain, and how often to check.
An incident titled Checkout returning 502: a timeline from the deploy to the recovery seven minutes later, beside the log lines from that window
An incident page: the deploy, the failed checks and the recovery on one timeline, with the log lines from those minutes. Sample data.