502 Bad Gateway: what it means and how to fix it (nginx, Cloudflare, load balancers)
The page you see came from the middleman, not the website itself. Something in front of the app (nginx, a CDN, a load balancer) asked the app for the page and got nothing usable back.
Who is saying what
Most sites have a chain: browser, then a CDN or load balancer, then a web server such as nginx, then the app (Node, Python, PHP-FPM). A 502 is sent by one of the middle links when the link behind it failed to give a proper HTTP response. So the cause is almost always the app or the connection to it, not the proxy that shows the error.
502 vs 503 vs 504
| Code | Meaning | Typical cause |
|---|---|---|
| 502 Bad Gateway | The backend gave no valid response | App not running, wrong port, app crashed mid-request |
| 503 Service Unavailable | The server is up but refusing work for now | Maintenance, overload, no healthy backends |
| 504 Gateway Timeout | The backend took too long | Slow query or slow upstream API, timeout too short |
All three can be retried, ideally with a growing delay. Anvil’s free HTTP status lookup lists retry advice for every status code.
Fixing it behind nginx
Start with the error log, usually /var/log/nginx/error.log. The message tells you which case you have:
| Log says | Meaning and fix |
|---|---|
connect() failed (111: Connection refused) while connecting to upstream | Nothing listens where proxy_pass points. Start the app, or fix the port. Same checks as localhost refused to connect. |
connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) | The PHP-FPM socket path in nginx doesn’t match the running PHP version, or PHP-FPM is stopped. |
(13: Permission denied) while connecting to upstream | nginx may not open the socket, or on SELinux systems it may not make network connections: setsebool -P httpd_can_network_connect 1. |
upstream prematurely closed connection | The app crashed or was killed during the request. Check the app’s own logs and memory (the kernel’s out-of-memory killer shows in dmesg). |
upstream sent too big header | Large cookies or headers: raise proxy_buffer_size (or fastcgi_buffer_size). |
no live upstreams | Every backend in the upstream block failed its checks recently. |
Two classic mix-ups: proxy_pass http://localhost:3000 where localhost resolves to IPv6 ::1 but the app listens only on 127.0.0.1 (write 127.0.0.1 explicitly), and nginx in Docker pointing at localhost, which is the nginx container itself rather than the app container (use the service name).
Cloudflare and other CDNs
- A 502 page with Cloudflare branding usually means your origin server answered badly or not at all. Cloudflare also has its own codes: 520 (origin sent an empty or odd reply), 521 (origin refused the connection), 522 (connection timed out), 523 (origin unreachable), 524 (origin too slow, over 100 seconds), 525/526 (TLS handshake or certificate problem between Cloudflare and the origin; an expired origin certificate is the classic 526, see certificate has expired).
- With a tunnel instead of open ports, a 502 often means the tunnel is up but the local service it points to is down or on another port.
- Cloud load balancers (AWS ALB and others) send 502 when the target closes the connection early. A common cause is the app’s keep-alive timeout being shorter than the load balancer’s idle timeout; make the app’s slightly longer.
If you are just visiting
There’s nothing wrong with your device. Reload after a minute, and if it persists, the site is down for everyone. Clearing cookies helps only in the rare “too big header” case.
App keeps restarting with exit code 137 or Killed in its logs? It is running out of memory: see exit code 137 and the OOM killer.
Related
Cloudflare Error 523 · Cloudflare Error 520 · Cloudflare Error 525 · Cloudflare Error 526 · Cloudflare Error 521 · Cloudflare Error 522 · Cloudflare Error 524 · HTTP 504 Gateway Timeout · HTTP 503 Service Unavailable · HTTP 429 Too Many Requests · ECONNRESET / read ECONNRESET · WebSocket connection failed · download won't resume
Questions
Is a 502 Bad Gateway my fault?
Almost never, if you are a visitor. It means a server in front of the website couldn't get a proper answer from the site's own app. Wait and reload.
What is the difference between 502 and 504?
502 means the backend answered badly or refused the connection. 504 means it didn't answer in time. 502 points to an app that is down or crashing, 504 to one that is slow.
How do I fix 502 Bad Gateway in nginx?
Read /var/log/nginx/error.log. “Connection refused” means the app isn't running on the proxy_pass address, a missing socket means PHP-FPM is stopped or misnamed, and “prematurely closed” means the app crashed during the request.
Should a client retry after a 502?
Yes, a 502 is usually temporary. Retry a few times with a growing delay, and only automatically for requests that are safe to repeat.
Published .