The NGINX 502 Bad Gateway error is one of the most common and frustrating issues you’ll encounter when running a web server. This error means NGINX received an invalid response from an upstream server—or couldn’t connect to it at all. In this comprehensive guide, you’ll learn every cause of the nginx 502 bad gateway error and exactly how to fix each one.
What Does NGINX 502 Bad Gateway Mean?
When NGINX acts as a reverse proxy or gateway, it forwards requests to upstream servers like PHP-FPM, Node.js, or other backend services. A 502 Bad Gateway error occurs when:
- The upstream server isn’t running
- NGINX can’t connect to the upstream server
- The upstream server sends an invalid or incomplete response
- Connection is refused or times out during the initial handshake
The NGINX source code defines 502 as the default error for any upstream failure that doesn’t map to a more specific status code. Understanding this helps you diagnose the root cause faster.
Quick Diagnosis: Check the Error Log First
Before diving into specific fixes, always check the NGINX error log. This log tells you exactly what went wrong:
tail -f /var/log/nginx/error.log
The error message reveals the specific cause. Here are the most common messages you’ll see with a 502 error:
| Error Message | Cause |
|---|---|
connect() failed (111: Connection refused) |
Upstream not listening on port |
connect() failed (2: No such file or directory) |
Socket file doesn’t exist |
connect() failed (13: Permission denied) |
Socket permission problem |
upstream sent too big header |
Buffer size too small |
upstream prematurely closed connection |
Upstream crashed during request |
Now let’s fix each cause systematically.
Cause 1: PHP-FPM Not Running
The most common cause of nginx 502 bad gateway errors is a stopped PHP-FPM service. When PHP-FPM isn’t running, the socket file disappears, and NGINX can’t forward requests.
Symptoms
Your error log shows:
connect() to unix:/run/php-fpm/www.sock failed (2: No such file or directory)
How to Fix
First, check if PHP-FPM is running:
systemctl status php-fpm
If it’s stopped or failed, start it:
systemctl start php-fpm
Check for startup errors:
journalctl -u php-fpm -n 50
Common reasons PHP-FPM fails to start include configuration syntax errors, missing extensions, or port conflicts. Fix any issues shown in the journal, then start the service again.
To prevent future outages, enable PHP-FPM to start automatically at boot:
systemctl enable php-fpm
Verify the Fix
Confirm the socket exists:
ls -la /run/php-fpm/www.sock
You should see the socket file. Then test your site—the 502 error should be gone.
Cause 2: Wrong Socket or Port Configuration
NGINX and PHP-FPM must agree on how they communicate. A mismatch causes connection failures and 502 errors.
Symptoms
Error log shows either:
connect() to unix:/run/php-fpm/www.sock failed (2: No such file or directory)
Or for TCP:
connect() failed (111: Connection refused)
How to Diagnose
Check what PHP-FPM is actually listening on:
grep -E "^listen\s*=" /etc/php-fpm.d/www.conf
This shows either a socket path or TCP address like 127.0.0.1:9000.
Then check your NGINX configuration:
grep -r "fastcgi_pass" /etc/nginx/
These must match exactly.
How to Fix
If PHP-FPM uses a socket:
# In your NGINX server block
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
If PHP-FPM uses TCP:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
After changing the configuration, test and reload NGINX:
nginx -t && systemctl reload nginx
For better performance with persistent connections, see our guide on NGINX FastCGI Keepalive.
Cause 3: Socket Permission Problems
Even when PHP-FPM runs and the socket exists, NGINX might lack permission to connect. This causes 502 errors with a specific permission denied message.
Symptoms
connect() to unix:/run/php-fpm/www.sock failed (13: Permission denied)
Understanding Socket Permissions
Unix sockets have file permissions like regular files. NGINX (running as the nginx user) needs read and write access to the socket.
Check current permissions:
ls -la /run/php-fpm/www.sock
If you see the socket owned by a group that nginx user isn’t part of, NGINX can’t connect.
How to Fix (Recommended Approach)
The proper way to handle PHP-FPM permissions is to create a dedicated user for each website. This provides better security isolation and avoids permission conflicts.
- Create a dedicated user for your website:
useradd example
- Configure the PHP-FPM pool (
/etc/php-fpm.d/example.conf) with matching ownership:
[example]
listen = /run/php-fpm/example.sock
listen.owner = example
listen.group = example
listen.mode = 0660
user = example
group = example
- Add the
nginxuser to the website user’s group:
usermod -aG example nginx
- Restart PHP-FPM to apply changes:
systemctl restart php-fpm
- Verify the new permissions:
ls -la /run/php-fpm/example.sock
You should see:
srw-rw---- 1 example example 0 Jan 24 10:00 /run/php-fpm/example.sock
The 502 error should now be resolved.
For a comprehensive guide on the proper permissions model for NGINX with PHP-FPM, see our article on NGINX and PHP-FPM permissions.
Cause 4: SELinux Blocking Connections
On RHEL-based systems (Rocky Linux, AlmaLinux, CentOS), SELinux can block NGINX from connecting to PHP-FPM sockets or network ports. This is a common cause that’s often overlooked. SELinux is one of the key security features that makes RHEL-based systems superior for web servers, but it requires proper configuration.
Symptoms
The error log shows permission denied, but file permissions look correct. Check for SELinux denials:
ausearch -m avc -ts recent
Or check if SELinux is in enforcing mode:
getenforce
How to Fix
For socket connections, enable the NGINX httpd network connect boolean:
setsebool -P httpd_can_network_connect 1
If using TCP to connect to PHP-FPM on a non-standard port:
semanage port -a -t http_port_t -p tcp 9000
For temporary testing, you can set SELinux to permissive mode:
setenforce 0
If this fixes the error, make the SELinux changes permanent and switch back to enforcing mode. Never leave SELinux disabled in production.
Cause 5: Upstream Sent Too Big Header
When PHP applications set many cookies or custom headers, the response headers can exceed NGINX’s default buffer size. This triggers a 502 error with a specific message.
Symptoms
upstream sent too big header while reading response header from upstream
This commonly happens with:
- E-commerce platforms setting multiple cookies
- Applications with large session data in headers
- APIs returning extensive custom headers
How to Fix
Increase the FastCGI buffer sizes in your NGINX configuration:
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Increase buffer sizes
fastcgi_buffer_size 32k;
fastcgi_buffers 8 32k;
fastcgi_busy_buffers_size 64k;
}
For proxy configurations, see our detailed guide on tuning proxy_buffer_size in NGINX:
location / {
proxy_pass http://backend;
proxy_buffer_size 32k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 64k;
}
The fastcgi_buffer_size (or proxy_buffer_size) handles the first part of the response containing headers. Increase this value until the error disappears.
Test and reload:
nginx -t && systemctl reload nginx
Finding the Right Buffer Size
To determine the optimal size, check what headers your application sends:
curl -sI https://your-site.com/page.php | wc -c
Set your buffer size to at least this value, rounded up to the next power of 2.
Cause 6: PHP-FPM Worker Pool Exhausted
When all PHP-FPM workers are busy, new requests queue up. If the queue fills, NGINX receives no response, causing 502 errors during traffic spikes.
Symptoms
Intermittent 502 errors under load. The PHP-FPM log shows:
WARNING: [pool www] server reached pm.max_children setting (5)
How to Diagnose
Check current PHP-FPM worker status:
pgrep php-fpm | wc -l
Compare with your configured maximum:
grep pm.max_children /etc/php-fpm.d/www.conf
How to Fix
Edit /etc/php-fpm.d/www.conf and increase the worker limits:
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
Calculate max_children based on available memory:
max_children = (Total RAM - RAM for other services) / Average PHP process size
Check average PHP process memory:
ps -ylC php-fpm --sort:rss | awk '{sum+=$9; count++} END {print sum/count/1024 " MB"}'
Restart PHP-FPM:
systemctl restart php-fpm
Cause 7: Upstream Timeout (May Show as 502)
While upstream timeouts typically result in 504 Gateway Timeout, misconfigurations can cause them to appear as 502 errors instead.
When This Happens
If the upstream starts responding but then times out mid-transfer, or if custom error handling intercepts the timeout.
How to Fix
Increase timeout values in your NGINX configuration:
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Increase timeouts
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 300s;
fastcgi_read_timeout 300s;
}
For proxy:
location / {
proxy_pass http://backend;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
Also increase the PHP execution time in /etc/php.ini:
max_execution_time = 300
Cause 8: Upstream Application Crashed
If PHP or your backend application crashes while processing a request, NGINX receives an incomplete response. This triggers a 502 error.
Symptoms
upstream prematurely closed connection while reading response header from upstream
Or in some cases, you see the generic 502 without specific details.
How to Diagnose
Check PHP-FPM logs:
journalctl -u php-fpm -n 100
Look for fatal errors, memory exhaustion, or segfaults.
Also check the PHP error log:
tail -f /var/log/php-fpm/www-error.log
Common Fixes
Memory limit issues:
Edit /etc/php.ini:
memory_limit = 256M
Segmentation faults:
Often caused by broken extensions. Disable recently added extensions and test:
php -m # List modules
OOM killer:
Check if the kernel killed PHP processes:
dmesg | grep -i "killed process"
If so, either increase server RAM or reduce PHP memory limits and worker counts.
Cause 9: Firewall Blocking Remote Upstream Connections
When NGINX proxies to upstream servers on remote hosts, firewall rules can block the traffic and cause 502 errors. This typically happens in multi-server architectures where NGINX and the backend run on different machines.
Symptoms
connect() failed (111: Connection refused)
Or:
connect() failed (113: No route to host)
This happens even though the upstream service is running on the remote server.
How to Diagnose
Check if the port is reachable from the NGINX server:
# Test TCP connectivity to remote backend
nc -zv backend-server.example.com 9000
# Or using curl
curl -v telnet://backend-server.example.com:9000
How to Fix
On the backend server, allow incoming connections:
# For firewalld
firewall-cmd --permanent --add-port=9000/tcp
firewall-cmd --reload
# For iptables
iptables -A INPUT -p tcp --dport 9000 -s nginx-server-ip -j ACCEPT
Also verify that the backend service is bound to the correct interface (not just localhost):
ss -tlnp | grep 9000
If it shows 127.0.0.1:9000, the service only accepts local connections. Update the backend configuration to listen on 0.0.0.0:9000 or the specific interface IP.
Cause 10: DNS Resolution Failure
When using hostnames in upstream definitions with dynamic resolution, NGINX needs a resolver configured. Without it, you get 502 errors.
Symptoms
The error log shows:
no resolver defined to resolve backend.example.com
How to Fix
Add a resolver directive to your NGINX configuration. For security and reliability, use your system’s local DNS resolver rather than hardcoding public DNS servers:
http {
# Use your system's DNS resolver (check /etc/resolv.conf)
# This is more secure than using public DNS like 8.8.8.8
resolver 127.0.0.53 valid=30s; # systemd-resolved
# Or use your network's DNS server from /etc/resolv.conf
resolver_timeout 5s;
server {
location / {
set $backend "backend.example.com";
proxy_pass http://$backend;
}
}
}
To find your system’s DNS resolver:
grep nameserver /etc/resolv.conf
Using the local resolver is recommended because:
- It respects your network’s DNS configuration
- It works with internal hostnames
- It doesn’t leak DNS queries to external servers
- It benefits from local DNS caching
Debugging Tips for Persistent 502 Errors
If you’ve tried the above fixes and still see 502 errors, use these advanced debugging techniques.
Enable Debug Logging
Temporarily enable debug logging in /etc/nginx/nginx.conf:
error_log /var/log/nginx/error.log debug;
Reload NGINX and reproduce the error. The debug log shows every step of the connection process.
Monitor Upstream Health
Watch connections in real-time:
watch -n1 "ss -s && echo '---' && ss -tnp | grep nginx"
Check System Resources
Verify the system isn’t resource-constrained:
# Check file descriptors
cat /proc/sys/fs/file-nr
# Check memory
free -h
# Check CPU
top -bn1 | head -5
Test Upstream Directly
Bypass NGINX and test the upstream directly:
# For PHP-FPM via socket
cgi-fcgi -bind -connect /run/php-fpm/www.sock
# For TCP backends
curl -v http://127.0.0.1:9000/
Preventing Future 502 Errors
After fixing the immediate issue, implement these preventive measures:
Set Up Monitoring
Use a proper monitoring solution to detect issues before users notice them. GetPageSpeed Amplify provides comprehensive NGINX monitoring with:
- Real-time metrics and alerts
- NGINX configuration analysis
- Security recommendations via Gixy
- Historical performance data
For a simple self-hosted check:
# Simple check script
curl -sS -o /dev/null -w "%{http_code}" https://your-site.com/ | grep -q 200 || echo "Site down!"
Enable Health Checks
Use NGINX upstream health checks (requires NGINX Plus or OpenResty):
upstream backend {
server 127.0.0.1:9000;
health_check interval=5s fails=3 passes=2;
}
Implement Graceful Degradation
Configure NGINX to serve a custom error page during outages:
error_page 502 /502.html;
location = /502.html {
root /var/www/errors;
internal;
}
Use Process Supervision
Ensure PHP-FPM restarts automatically if it crashes. Systemd does this by default, but verify:
grep Restart /usr/lib/systemd/system/php-fpm.service
You should see Restart=on-failure or similar.
Summary
The nginx 502 bad gateway error has many causes, but they all share one thing: NGINX couldn’t get a valid response from the upstream server. Here’s a quick checklist:
- Check if the upstream is running – Start PHP-FPM or your backend service
- Verify socket/port configuration – NGINX and upstream must match
- Check socket permissions – NGINX user needs access
- Review SELinux settings – Enable necessary booleans
- Increase buffer sizes – For large header responses
- Scale PHP-FPM workers – Handle traffic spikes
- Adjust timeouts – For slow operations
- Check for crashes – Review application logs
- Verify firewall rules – For remote upstream connections
- Configure DNS resolver – Use local resolver for dynamic upstreams
Always start with the error log—it tells you exactly what failed. With this guide, you can diagnose and fix any 502 error quickly and confidently.

