How to Find the Root Cause of Nginx 502 Bad Gateway

An HTTP 502 error stops you cold. Users see a vague failure page, and your monitoring lights up with alerts. Here is the hard truth: Nginx is only the messenger. The real problem lives somewhere behind your reverse proxy.
This guide gives you a step-by-step method to find the root cause of a 502 bad gateway error in Nginx. You will learn how can I find the root cause step by step? by starting at proxy error logs, then moving outward through upstream services, network rules, Nginx configuration, and system security layers. Each layer narrows the search.
If you follow this sequence, you will stop guessing and start fixing the actual problem behind every 502.
Start with Proxy Error Logs to Diagnose a 502 Bad Gateway
When you face an http 502 error, your first move should always be the proxy error logs. These logs tell you exactly why the reverse proxy returned a 502. Do not check the application yet. Do not tweak timeouts. Start with the proxy error logs. The message Nginx writes there directly identifies the root cause. This approach saves hours of guesswork. Every bad gateway error in nginx starts with a clue in these logs. You do not need to guess what caused the error. The log gives you the answer immediately.
Locate the Nginx Error Log
You need to check the nginx error logs first. The default location is /var/log/nginx/error.log. Many distributions also use /var/log/nginx/your-site-error.log for individual server blocks. To confirm the exact path, inspect your Nginx configuration file. Look for the error_log directive. The path follows immediately after that directive.
Once you locate the file, tail it in real time. Use the command tail -f /var/log/nginx/error.log. Reproduce the 502 bad gateway error while the command runs. New log lines appear as the error occurs. You see the exact second Nginx returns the error.
You can also use grep to filter specific messages. Run tail -f /var/log/nginx/error.log | grep upstream. This shows only lines containing the word upstream. Filtering helps you focus on proxy-related errors. Ignore unrelated entries about static files. Focus only on messages containing upstream or connect.
Read Common Log Messages
Open the error log. Watch for four common patterns. Each pattern tells a different story about the upstream. Here is a table of the most frequent messages, what they mean, and your next step:
| Log message | Likely cause | Next action |
|---|---|---|
connect() failed (111: Connection refused) | Application stopped or proxy_pass uses the wrong port | Check the service listener and active configuration |
upstream timed out | Slow application, database, or exhausted worker pool | Trace latency and resource pressure before raising timeouts |
upstream prematurely closed connection | Application crash, reset, or response failure | Correlate the application log and process restart time |
no live upstreams | Every backend in the pool is unavailable | Check health checks, deployment state, and upstream addresses |
The most common error message is connect() failed (111: Connection refused). This error means the upstream server is down. The application process has crashed. Or it never started. Or the proxy points to the wrong port. The proxy receives a connection refusal. No application listens at that address.
The second most frequent pattern is upstream prematurely closed connection. The proxy sends a request to the upstream. The upstream starts processing. Then it disconnects before sending a complete response. This behavior indicates one of two conditions:
- The upstream server may disconnect due to a timeout setting that is too short. The proxy then receives a FIN or RST packet before the request completes.
- The upstream application may crash during processing. No process listens on the port. The OS kernel sends an RST packet to the proxy.
- In both cases, the proxy interprets the premature closure as an invalid response to nginx. The result is a 502 Bad Gateway.
So when you see this message, check the upstream application logs. Look for crash traces. Look for timeout limits. The application tells you why it disconnected.
Verify the Upstream Server Is Running
A crashed or never-started backend is the most common cause of a 502 bad gateway. After reviewing the proxy error logs, your next logical step is to verify that the upstream application actually listens for requests. The error log told you which upstream address failed. Now you confirm whether the process behind that address is alive. This step alone resolves the majority of nginx incidents that produce this error message. Do not skip it. The goal is to ensure the upstream server is running before you check any other layer. When nginx receives an invalid response from an upstream server, it returns the error code you see. An invalid/no response from upstream triggers the same behavior. Understanding these messages helps you connect the error log to the actual problem.
Check Service Status
Most Linux distributions manage application services with systemd. You can check whether an upstream service like PHP-FPM or Gunicorn is active with a single command. Open a terminal on the upstream host and run the generic status check:
systemctl status <service-name>— a generic command that can be used to check the status of any systemd-managed service, including Node.js, PHP-FPM, or Gunicorn.
Replace <service-name> with your actual service name. For a PHP-based application, the specific command uses the version number:
sudo systemctl status php8.1-fpm— used to check the status of the PHP-FPM service.
The output displays one of three states: active, inactive, or failed. If you see active with the label running, the service is alive. If you see inactive or failed, start the service with sudo systemctl start <service-name>. Then test whether the 502 disappears. If the service is active but the error persists, move to the next subheading. You may also see an upstream server is unavailable message in the error logs when the service fails to start.
If you use Node.js, confirm the process is alive with ps aux | grep node. Also check the application logs at the same time. Node.js applications often crash silently without notifying the process manager. A stopped Node process leaves no error in system logs. You must check its own log file to see why it exited. Tools like PM2 can restart the process automatically, but the root cause still requires investigation in the logs.
Test Port and Connectivity
A running service does not guarantee it listens on the expected port. The application may start on a different interface or port than the one you configured in nginx. This mismatch causes an upstream server is unavailable scenario. Nginx tries to connect, finds nothing, and updates the status to upstream server down. The error log then records the failure.
Use curl -v http://localhost:PORT from the Nginx host to test direct connectivity. Replace PORT with the upstream port. A successful response shows the application output. A Connection refused message confirms the port mismatch. In that case, check which port your application actually binds to, then update the proxy_pass directive to match. You can also use telnet as an alternative test. Run telnet <upstream-ip> <port> from the Nginx host. A successful connection shows a blank screen with the cursor blinking. A failure shows Connection refused.
For Nginx Proxy Manager users, a 502 can appear even when the scheme and port look correct in the admin interface. Verify the upstream container or service directly by running curl inside the Nginx container or from the host that runs Nginx Proxy Manager. The web interface does not always reflect runtime conditions.
If curl succeeds but Nginx still returns a 502 bad gateway error, the issue may involve timeouts, buffers, or a different layer. But if curl fails, you have confirmed that the upstream server is unreachable. Fix the application listener, then proceed.
Rule Out Firewall and Network Blocks
A firewall rule or cloud security group can silently block traffic between nginx and the upstream server. The application runs fine. The port listens correctly. Yet nginx still returns a 502 because a packet filter drops the connection attempt. This layer sits between two healthy services, so it often escapes notice.
Inspect Firewall Rules
Start by listing the active rules on the nginx host. The command iptables -L -n -v shows the rules and matching traffic for all chains, including INPUT, OUTPUT, and FORWARD. You can use this output to verify whether traffic to a specific upstream port is permitted. A simpler view comes from iptables -L, which lists all currently active rules in the default table. This gives you a full picture of the firewall configuration.
Two more commands help you audit the ruleset:
sudo iptables -S— Displays the current ruleset in a format you can save or reuse. Sample output shows the default policies for INPUT, FORWARD, and OUTPUT chains (all set to ACCEPT) with no additional rules present.sudo iptables -L— Displays the rules in a more readable, tabular format. Sample output shows the INPUT, FORWARD, and OUTPUT chains with their default policies and any active rules (for example, an ACCEPT rule for RELATED,ESTABLISHED connections).
If you run nginx inside a cloud environment, check the security group or network ACL for that instance. These controls live outside the host and block traffic before iptables ever sees it.
Test with curl and telnet
Reading rules tells you what should happen. Testing tells you what actually happens. Run curl -v http://<upstream-ip>:<port> from the nginx host. A successful response proves the path works. A hang or refusal points to a block or a dead listener.
Use telnet <upstream-ip> <port> as a second check. A blank screen with a blinking cursor means the connection opened. A refusal or timeout confirms a block. If both tests fail while the service runs locally, a firewall rule or security group is your root cause. Fix the rule, then retest. The 502 should clear once nginx can reach the upstream again.
Tune Timeouts and Buffer Sizes
A slow upstream can trigger a timeout that nginx reports as a 502. The proxy waits for a response. The backend takes too long. Nginx gives up and returns the error. You see a gateway failure, but the real issue is latency. This scenario often involves slow responses from upstream servers that eventually complete, just not within the configured window.
Adjust proxy_read_timeout and proxy_connect_timeout
Two directives control how long nginx waits. The proxy_connect_timeout directive sets the limit for establishing a connection to the upstream. The proxy_read_timeout directive defines how long nginx waits between reads from the upstream. When either limit expires, nginx closes the connection and returns a 502.
Choose values based on your application’s normal response time. A database-heavy page may need a longer read timeout. A simple API endpoint may need less. Test after each change. Raising timeouts masks the symptom if the upstream is genuinely slow. Investigate the application performance first.
Increase proxy_buffer_size for Large Headers
Oversized response headers can also cause a 502. Nginx allocates a buffer for upstream response headers. The default size is 4k or 8k. When headers exceed this limit, nginx cannot process the response and returns an error.
According to the source, applications such as Laravel with verbose session cookies, some SSO implementations, and those returning many Set-Cookie headers commonly exceed the default proxy_buffer_size of 4k or 8k, leading to a 502 error. Increasing proxy_buffer_size beyond the default is necessary in these cases to prevent the error.
Set proxy_buffer_size to a larger value when you identify this pattern. Also consider proxy_buffers and proxy_busy_buffers_size for related tuning. Monitor the error log after changes. The header-related 502 should disappear once the buffer accommodates the full response.
Confirm the Upstream Address in Nginx Config
A typo in the upstream name or port is a frequent root cause. You might point nginx to the wrong address. The result is a 502 that persists even when the application runs fine. You need to check nginx config carefully before moving to other layers.
Check proxy_pass and upstream Blocks
The proxy_pass directive tells nginx, acting as a reverse proxy, where to forward requests. If you set this directive to a hostname that does not exist or a port number that no service uses, the nginx config contains a mistake. Open your nginx configuration file. Look for the proxy_pass line inside the relevant location block. Compare it to the actual address of your upstream application. A common error involves typing the wrong port or socket path. For example, your application might listen on port 8080, but you wrote 8081. This mismatch causes a 502. You can also check the upstream block if you use one. The upstream block defines a group of servers. The server assigns a name to the group, and proxy_pass references that name. A typo in the referenced name leads to the same issue. Always verify that you use the right upstream server and port. Run a direct curl test from the host to confirm the address works. This step saves time and avoids unnecessary debugging.
Verify Location Block Order
Nginx processes location blocks in a specific order. It first matches prefix locations, then regex locations in the order they appear. The first matching location block handles the request. If you configure multiple location blocks that could match the same URI, the wrong block might handle the request and forward it to a wrong upstream server. For instance, you might have a location block for /api that proxies to backend A and a location block for / that proxies to backend B. A request to /api/login could match the / location if the /api block uses a different matching rule. The request then goes to backend B, which cannot handle it, and a 502 appears. You can avoid this by checking nginx configuration for location block order. Place more specific blocks before catch-all blocks. Use the = modifier for exact matches when possible. Test with curl to see which location block handles your request. Understanding location block precedence helps you fix these routing errors quickly. Once you confirm the order, the 502 often disappears.
Fix PHP-FPM and Socket Permissions
PHP-FPM is a common upstream for nginx. A stopped pool or an incorrect listen directive triggers a 502 error. You must verify pool status and socket permissions. These two checks resolve most PHP-FPM related 502 issues.
Verify PHP-FPM Pool Status
Check PHP-FPM pool status with sudo systemctl status php8.1-fpm. Adjust the version number to match your installation. The output shows if the pool is active and running. If inactive or failed, start it with sudo systemctl start php8.1-fpm. This step often resolves the 502 immediately.
Next, verify the listen directive in the PHP-FPM pool configuration. This file lives at /etc/php-fpm.d/www.conf. The listen directive defines the address or socket path. A mismatch between this path and the fastcgi_pass directive in your nginx configuration causes the 502. Run grep '^listen =' /etc/php-fpm.d/www.conf to see the current setting. Compare it with the nginx configuration. They must match exactly. For a Unix socket, the path must be identical. For a TCP address, the port must match.
Correct Unix Socket Ownership
When the listen directive uses a Unix socket, file permissions matter. Nginx needs read and write access to the socket file. Incorrect ownership blocks the connection. The table below shows typical permission settings.
| Setting | Default / Example Value | Purpose |
|---|---|---|
| listen.owner | nobody (commented default) | Unix socket owner |
| listen.group | nobody (commented default) | Unix socket group |
| listen.mode | 0666 (commented default) | Permissions; read/write required |
| user | apache | PHP-FPM process user |
| group | apache | PHP-FPM process group |
The socket directory also needs correct ownership and permissions. The command below shows a proper setup.
Resolve TLS Handshake Failures
An HTTPS upstream adds another failure point. Nginx connects to the backend, starts the TLS handshake, and the negotiation fails. The proxy never receives a valid response, so it returns a 502. Certificate problems and protocol mismatches both produce this result, and neither one leaves an obvious clue in the access log.
Validate Upstream Certificates
An expired certificate, a self-signed certificate, or a certificate issued for the wrong hostname will break the handshake. Nginx rejects the upstream identity and closes the connection. Test the upstream directly from the nginx host before you change any configuration. The openssl s client tool shows you the full certificate chain and the verification result.
The certificate check passes only when the output reports successful verification, such as Verify return code: 0 (ok) or Verification: OK. Any other return code points to the root cause. Replace the hostname and port with your own upstream values. If you rely on a private CA, confirm that the CA file matches the one your nginx configuration references.
Match Protocols and Ciphers
A protocol or cipher mismatch also ends the handshake. The upstream may accept only TLS 1.2 while nginx offers a different version, or the two sides may share no common cipher suite. The connection attempt fails, and the proxy reports a 502 to the client.
Check the protocol and cipher settings on both sides. Compare the ssl_protocols and ssl_ciphers directives in your nginx configuration against the upstream server’s accepted values. Widen the overlap by enabling a protocol version or cipher suite that both systems support. After each change, reload nginx and retest the upstream with openssl s client. A successful handshake confirms the fix.
You now have a repeatable path. Start with proxy error logs, then check the upstream service, network rules, nginx configuration, and security layers. This sequence answers how can i find the root cause step by step? without guesswork.
Keep this checklist handy for the next incident:
- Read the nginx error log first.
- Confirm the upstream process runs and listens.
- Test reachability with curl or telnet.
- Verify proxy_pass, timeouts, and buffers.
- Check SELinux, AppArmor, and TLS settings.
A 502 bad gateway error rarely appears twice for the same reason. Monitor upstream health, review logs often, and follow nginx proxy best practices. That habit prevents most 502 events.
FAQ
What causes most 502 bad gateway errors?
A dead or unreachable upstream server causes most of these failures. The backend process may have crashed, stopped, or never started. Check the proxy error log first. The message there usually points straight to the upstream problem.
How do I know if the problem is Nginx or the backend?
The nginx error log tells you. A connection refused message means the backend is down. A timeout message means the backend is slow. Nginx only reports the failure. The backend owns the actual fault.
Can a firewall cause a 502 even when the app runs fine?
Yes. A firewall rule or cloud security group can drop packets between nginx and the upstream. The service looks healthy on its own host. Test reachability with curl or telnet from the nginx host to confirm a block.
Why does a 502 appear only under heavy traffic?
Resource exhaustion explains this pattern. The upstream worker pool fills up, or the database slows down. Nginx waits, then times out. Review upstream performance metrics before you raise timeout values.
How can I find the root cause step by step?
Start with the proxy error log. Then verify the upstream process runs and listens. Test network reachability next. Check configuration, timeouts, and security policies after that. Each layer narrows the search until you reach the real fault.
