A 502 Bad Gateway means a server acting as a gateway or proxy received an invalid response, or no response, from the server behind it. The page you see is not the real problem; it is the proxy reporting that something upstream broke. This guide shows how to identify which hop failed, read the log line that names the cause, and fix the common versions of the problem.
The definition comes from HTTP semantics (RFC 9110): a gateway got an invalid response from an inbound server while trying to fulfil the request. See also the HTTP 502 reference.
First, work out who is the "gateway"
In a modern site there are often several proxies stacked in a row:
Browser -> CDN (e.g. Cloudflare) -> load balancer -> nginx/Apache -> PHP-FPM / Node / Gunicorn -> database
Any element that forwards a request can generate a 502 for the one behind it. So the first question is which layer produced the page. Clues:
- The error page has a CDN logo, a Ray ID, or says "Bad gateway" with a host list: the CDN itself generated it. Cloudflare commonly shows 502 when its edge cannot get a valid response, but origin problems often show as 52x codes instead (see Cloudflare 520 to 526 errors).
- A bare, plain
502 Bad Gatewaywithnginxat the bottom: nginx is your gateway. - A page titled "Proxy Error": Apache with
mod_proxy. - Response headers show
Server:andVia:values. Check them:
curl -sI https://example.com/ | head -n 15
The HTTP Header Checker shows the same information from outside your network.
Read the error log, which names the cause
Almost every 502 has a precise line in the gateway's error log. This is the fastest diagnostic available.
# nginx
sudo tail -n 100 /var/log/nginx/error.log
# Apache (Debian/Ubuntu path; RHEL uses /var/log/httpd/error_log)
sudo tail -n 100 /var/log/apache2/error.log
# live view while you reproduce the error
sudo tail -f /var/log/nginx/error.log
The common nginx messages and what they mean:
| Log message | Meaning | Where to look |
|---|---|---|
connect() failed (111: Connection refused) while connecting to upstream | Nothing is listening at the upstream address | Backend service stopped or wrong socket/port |
connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) | Socket path does not exist | PHP version mismatch or FPM down |
connect() to unix:... failed (13: Permission denied) | nginx user cannot access the socket | Socket owner/group, listen.owner |
upstream prematurely closed connection while reading response header | Backend crashed or was killed mid-request | App crash, OOM kill, segfault |
recv() failed (104: Connection reset by peer) | Backend dropped the connection | Worker restarts, request limits |
upstream sent too big header while reading response header from upstream | Response headers exceed buffer | Increase buffers, reduce cookie size |
no live upstreams while connecting to upstream | All servers in an upstream group are marked failed | Backends down or failing health thresholds |
Note that upstream timed out is a different animal: that yields a 504, covered in fix 504 Gateway Timeout.
Fixes by stack
PHP-FPM behind nginx or Apache
This is the most common situation on WordPress and Laravel servers.
sudo systemctl status php8.3-fpm # use your version
sudo journalctl -u php8.3-fpm --since "1 hour ago"
sudo tail -n 50 /var/log/php8.3-fpm.log
ls -l /run/php/
Check the following, in order:
- Is FPM running? If not, start it and read why it stopped.
- Does the socket or port in nginx match FPM? The
fastcgi_passvalue must equallistenin the pool file (/etc/php/8.3/fpm/pool.d/www.conf). After a PHP upgrade, the socket name changes, and nginx is still pointing at the old one. That is a classic post-upgrade 502. - Are workers exhausted? A log line such as
server reached pm.max_children setting (N), consider raising itmeans all workers were busy. Raisingpm.max_childrenhelps only if memory allows. Estimate:max_childrenis roughly the memory available for PHP divided by the average memory of one worker (measure withps --no-headers -o rss -C php-fpm8.3). Setting it higher than RAM allows trades a 502 for the OOM killer. - Did workers crash? A segfault in
dmesg -T | grep -i segfaultoften points to a faulty PHP extension, such as an incompatible opcache or a third-party module. - Is a worker being killed for running too long?
request_terminate_timeoutkills a script, and the proxy sees a broken connection.
After changing config, validate and reload:
sudo nginx -t && sudo systemctl reload nginx
sudo php-fpm8.3 -t && sudo systemctl restart php8.3-fpm
Node.js, Python (Gunicorn, uWSGI) and other app servers
The pattern is the same: the proxy cannot reach the process.
sudo systemctl status myapp
sudo ss -tlnp | grep 3000 # is anything listening on the expected port?
curl -sv http://127.0.0.1:3000/ -o /dev/null
journalctl -u myapp -n 100 --no-pager
If curl to the app directly fails, nginx is not at fault. Typical causes are an uncaught exception that crashed the process with no supervisor restarting it, the app binding to 127.0.0.1 while nginx proxies to another address (or to a container's internal IP), or an environment variable missing after a redeploy. Run the app under systemd, PM2 or a container restart policy so that crashes self-heal.
Apache with mod_proxy or PHP-FPM via proxy_fcgi
Look for "AH01114: HTTP: failed to make connection to backend" or "AH00957" in the error log. Both mean the backend address is wrong or down. If workers are saturated you may see "server reached MaxRequestWorkers setting", but that more typically produces slow responses or 503. Confirm the ProxyPass target and the backend service.
Large headers and cookies
If the log says upstream sent too big header, the backend returned more header data than nginx's buffer. This often follows a login plugin that sets huge cookies or debug headers. Increase the buffers for the relevant module:
# for FastCGI (PHP-FPM)
fastcgi_buffer_size 32k;
fastcgi_buffers 16 16k;
# for proxy_pass upstreams
proxy_buffer_size 16k;
proxy_buffers 8 16k;
Reducing the cookie or header size at the source is the better long-term fix.
Cloudflare and other CDNs
When Cloudflare shows a branded 502, test the origin directly as in the earlier tip. Cloudflare's published guidance also lists reasons such as an origin that sends malformed headers or resets connections. If your page shows 52x codes, use the Cloudflare एरर चेकर. Make sure your origin firewall is not rate limiting or blocking Cloudflare's published IP ranges, since all traffic arrives from them and a firewall that treats them as one noisy client can drop connections.
IIS and Windows
On IIS with Application Request Routing, the substatus codes help: 502.3 is a connection failure to the backend (often timeouts or resets), and 502.5 or 502.5 ANCM indicates an ASP.NET Core process failure. Open Event Viewer (Application log) and the ASP.NET Core module's stdout log. Check that the app pool is running and the hosting bundle is installed for the .NET version you deployed.
Fix intermittent 502s
A 502 that appears for a few seconds after every deploy usually means the backend restarts while the proxy still routes to it. Use a graceful reload (systemctl reload php8.3-fpm, nginx -s reload) or rolling deploys behind a load balancer with health checks. A 502 that arrives with traffic spikes suggests exhausted workers. A 502 on one specific URL points to a code path that crashes, so find it in the app log by timestamp.
If errors are random and rare, check for backend processes recycled by a request limit (pm.max_requests, Gunicorn max_requests), which can drop an in-flight connection when misconfigured, and for keep-alive mismatches where the proxy reuses an upstream connection the backend has already closed. Setting the backend's keep-alive timeout higher than the proxy's idle timeout avoids that race.
A decision path you can follow
- Request the page. Note the exact page text and headers to identify the gateway.
- Check the gateway's error log for the matching entry.
- If it says connection refused or no such file: the backend is down or addressed wrongly. Start the service, fix the socket path.
- If it says reset or closed prematurely: read the backend's own log and
dmesgfor crashes and OOM kills. - If it says too big header: increase buffers.
- If the origin works directly but the CDN shows errors: investigate allow-listing, SSL mode and origin timeouts.
- If you cannot see logs: contact your host.
When to call your host
On shared and managed hosting you usually cannot restart PHP-FPM or read the proxy logs. Open a ticket if a refresh does not clear the error within a few minutes, and include the URL, UTC time, response headers and any error ID shown. Ask specifically whether the PHP handler or the account's processes crashed or hit a resource limit. If it affects all your sites at once, it is probably a server-wide problem on their side.
अगले कदम
Related tools and guides:
- HTTP स्टेटस चेकर to confirm what your URL really returns
- HTTP Header Checker to identify which proxy generated the error
- पोर्ट चेकर to test that the origin port is reachable
- Fix 504 Gateway Timeout
- Fix 503 Service Unavailable
- Why is my website down?
सामान्य प्रश्न
Is a 502 error my fault or the website's fault?
If you are a visitor, it is almost never your fault. The gateway on the site's infrastructure got a bad response from its backend. Refreshing after a minute sometimes works, because the issue may be transient.
What is the difference between 502, 503 and 504?
A 502 means the gateway got an invalid response or could not connect. A 503 means the service is unavailable, often overloaded or in maintenance. A 504 means the backend did not answer in time. Logs often distinguish them: refused or reset connections give 502, timeouts give 504.
Why do I get 502 only after a PHP update?
Updating PHP often changes the FPM service name and socket path, for example from php8.2-fpm.sock to php8.3-fpm.sock. If nginx or Apache still points at the old socket, every request fails with a 502 until the web server config is updated and reloaded.
Can a plugin or theme cause a 502?
Yes, if it makes PHP crash (segfault, memory exhaustion that kills the worker) or runs so long that a terminate timeout fires. Disable recently added plugins and check the PHP-FPM log for crashes around the time of the error.
Will increasing timeouts fix a 502?
Usually not, because 502 is about an invalid or refused connection, not slowness. Timeout settings matter for 504. Raise them only after the log shows timeouts rather than refused or reset connections.
Get notified when this guide updates
Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.
यह पेज सामान्य जानकारी है, जिसे हमारी संपादकीय टीम ने लिखा है और दस्तावेज़ीकरण बदलने पर अपडेट किया जाता है। सर्वर और प्रदाता अलग-अलग होते हैं, इसलिए बदलाव पहले सुरक्षित तरीके से जाँचें। देखें: संपादकीय नीति और अस्वीकरण.