Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
VGSources
Blog

How to Fix an Nginx Reverse Proxy 502 Error (Step-by-Step)

A practical, log-first guide to fixing Nginx reverse-proxy 502 errors, from refused connections and container networking to URI rewrites, TLS mismatches, timeouts, invalid headers, and upstream queues.
Length12 min Posted Quest giverVGSources Team
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

An Nginx 502 Bad Gateway means Nginx could not obtain a valid response from the upstream application it was proxying to. The fastest reliable fix is to reproduce one failure, read the active Nginx error log, identify the upstream address and failure phase, test that address directly from the Nginx host or container, and then correct the service endpoint or proxy configuration. Do not start by increasing timeouts: a stopped service, wrong port, protocol mismatch, malformed headers, or an unreachable container will continue to return 502 until its underlying cause is fixed.

What a 502 means in an Nginx reverse-proxy setup

Nginx sits between the client and an application server. It accepts the client request, sends that request to a configured upstream, waits for the upstream response, and returns the response to the client. The official Nginx description is: “When NGINX proxies a request, it: 1. Sends the request to a specified proxy server 2. Fetches the response 3. Sends the response back to the client.” A 502 means that exchange failed; it does not, by itself, identify whether the failure was caused by networking, the application, TLS, routing, headers, or an upstream pool.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The same gateway-error principle applies when Nginx uses proxy_pass for HTTP, fastcgi_pass for FastCGI, uwsgi_pass for uWSGI, scgi_pass for SCGI, or memcached_pass for Memcached. The directive tells Nginx where and how to connect; the error log tells you which part of that connection failed.

Start with the error log, not the browser message

Find the active log

Common package installations write errors to /var/log/nginx/error.log. The exact path depends on how Nginx was installed and on the configured error_log directive. Official Debian, Ubuntu, and RHEL packages commonly use that path. Container images often send the error log to container standard error instead, so inspect the container runtime logs rather than assuming a file exists.

# Show the configured files and syntax context
nginx -T 2>/dev/null | grep -nE 'error_log|access_log|proxy_pass'

# Traditional package installation
tail -f /var/log/nginx/error.log

# Docker container (replace the name)
docker logs -f nginx

# Systemd service (replace the unit if necessary)
journalctl -u nginx -f

If you have several server blocks or a custom log path, use the configuration dump to locate the log that applies to the failing virtual host. A stale log from another server block can send troubleshooting in the wrong direction.

Reproduce one request and capture the exact line

Keep one terminal following the error log, then make a single request to the URL that returns 502. Copy the complete log line, including the upstream address and the wording after it. Common patterns are:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • connect() failed or connection refused: Nginx reached the network stack but no usable listener accepted the connection.
  • upstream timed out (110: Connection timed out) while connecting to upstream: connection establishment did not complete in time.
  • upstream timed out ... while reading response header from upstream: a connection was made, but the application did not send headers before the read timeout.
  • upstream sent invalid header: the upstream response was malformed or ended before valid headers were received.
  • TLS or SSL handshake messages: the scheme, certificate, SNI, trust, or TLS settings do not match the upstream.
  • Queue or server-selection errors: Nginx could not select a usable member in the configured upstream group.

The address shown after upstream: is especially valuable. Compare its host, IP, port, and scheme with the endpoint you believe the application uses. A 502 from a completely different address often means you edited the wrong server block or deployed an old configuration.

Add timing and upstream fields to access logs

For recurring failures, include upstream variables in an access-log format. Nginx defines $upstream_addr as the selected upstream address, $upstream_connect_time as connection time, $upstream_header_time as time until the first response headers, $upstream_response_time as time until the complete response, and $request_time as total request time.

log_format upstream_debug '$remote_addr $request status=$status '
                          'upstream=$upstream_addr '
                          'connect=$upstream_connect_time '
                          'header=$upstream_header_time '
                          'response=$upstream_response_time '
                          'total=$request_time';

access_log /var/log/nginx/access.log upstream_debug;

A very small connect time followed by a long header time points toward application startup, a slow dependency, or a handler that never begins its response. A failure with no connect time usually indicates DNS, routing, a refused connection, or an upstream-selection problem.

Test the upstream directly from Nginx’s network location

Testing from your laptop is not enough. Nginx may run on another host, inside a container, or on a network with different DNS and firewall rules. Run the request from the Nginx host, or open a shell inside the Nginx container or pod.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
# Replace the host, port, and path with the values in proxy_pass
curl -v http://127.0.0.1:8000/health

# Test a named service from inside a container network
curl -v http://app:8000/health

# Check name resolution from the same runtime
getent hosts app

# Confirm a TCP listener (use the actual port)
ss -ltnp | grep ':8000'

Interpret the result rather than only checking whether curl exits successfully:

  • Connection refused: no process is listening at that address and port, the port is wrong, or the request crossed a namespace boundary where 127.0.0.1 refers to the wrong machine.
  • Connection timed out: routing, security groups, a firewall, or a broken network path is preventing reachability.
  • HTTP response received: compare the direct status, headers, and path with what Nginx sends. A healthy response on one path does not prove that the proxied path is correct.
  • Name cannot be resolved: fix container-network membership, DNS, or the hostname in the upstream definition before changing timeout values.

Fix the common 502 causes

1. The application is stopped or listening on another port

Check the application service status and its own logs. Then verify the listener on the exact interface and port configured in Nginx. An application bound only to a private interface may not be reachable through an address that resolves to a different interface. Conversely, an application bound to a container’s loopback interface is not reachable through the container’s service address.

# Examples; use the service manager and process name used by your application
systemctl status my-app
systemctl restart my-app
ss -ltnp | grep ':8000'

Do not “fix” a refused connection by raising proxy_read_timeout. Nginx cannot wait for a process that is not listening. Correct the port, start the service, or update proxy_pass to the listener that actually exists.

2. The host, IP address, or container name is wrong

proxy_pass may contain a domain name, an IP address, and an optional port. Verify DNS resolution from the Nginx runtime, not only from an administrator workstation. In a container deployment, make sure both containers are attached to the same network and that the service name is the name visible on that network. Check firewall rules and cloud security policies when the upstream is on another host.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If the upstream permits only certain source networks and Nginx has multiple interfaces, proxy_bind can select the required source address:

location /api/ {
    proxy_bind 10.0.2.15;
    proxy_pass http://api.internal.example:8080;
}

Use that directive only when the upstream’s routing or access policy requires a specific source address. Binding to an address that is not present on the Nginx host creates another connection failure.

3. Loopback and container namespaces are being confused

127.0.0.1 always means “this network namespace.” If Nginx runs in a container, proxy_pass http://127.0.0.1:8000 points to Nginx’s container, not to an application running on the host or in a separate container. Use the host gateway address where supported, a service name on the shared container network, or the application’s reachable private IP. Confirm the choice with a direct curl executed inside the Nginx runtime.

4. The URI and trailing slash do not match what the application expects

The URI portion of proxy_pass changes path rewriting. When proxy_pass includes a URI, Nginx replaces the part of the normalized request URI that matched the location. When it has no URI, Nginx passes the full request URI, subject to Nginx’s documented normalization rules.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Configuration Client request Typical upstream path
location /api/ { proxy_pass http://app:8000/; } /api/users /users
location /api/ { proxy_pass http://app:8000; } /api/users /api/users
location / { proxy_pass http://app:8000/v1/; } /health /v1/health

The exact behavior depends on the location and URI syntax, so compare the path expected by the application with the path Nginx actually sends. A wrong path can lead to an application-level error, an early close, or a route that never produces valid headers. Test the candidate path directly with curl -v before changing the location block.

5. Nginx is speaking HTTP to an HTTPS upstream, or the reverse

Use proxy_pass http://... when the upstream speaks plain HTTP and proxy_pass https://... when it expects TLS. A scheme mismatch usually appears in the error log as a handshake or protocol error, not as a generic application timeout.

location /secure-api/ {
    proxy_ssl_server_name on;
    proxy_pass https://api.example.internal:8443;
}

For HTTPS upstreams, verify all of the following:

  • The certificate name matches the hostname Nginx sends through SNI.
  • The upstream supports the TLS versions and ciphers enabled by Nginx.
  • The trust configuration is appropriate when Nginx validates the upstream certificate.
  • The upstream port is a TLS port rather than a plain HTTP listener.

Increasing proxy_read_timeout cannot repair a failed TLS handshake. Fix the scheme, hostname, SNI, trust, or certificate problem identified in the log.

6. A connect or read timeout is hiding the real delay

Separate connection establishment from application response time. $upstream_connect_time shows how long connection setup took; $upstream_header_time shows how long Nginx waited for response headers. A long connect time suggests routing, firewall, saturation, or a slow TCP/TLS setup. A short connect time followed by a long header time points to the backend or one of its dependencies.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Nginx provides three commonly adjusted proxy timers:

Directive What it limits Change it when
proxy_connect_timeout Time allowed to establish the upstream connection The log shows connection establishment is genuinely slow and the network path is healthy
proxy_send_timeout Time between writes while sending the request upstream The upstream accepts connections but cannot receive request data promptly
proxy_read_timeout Time between reads while receiving the upstream response The application legitimately needs longer to produce or stream a response

Nginx treats connection errors, timeouts, denied connections, and invalid headers as unsuccessful upstream attempts. Set the smallest timeout that accommodates the documented workload, and investigate application latency before making a large increase. A longer timeout can consume worker connections and make an outage worse when the backend is down.

7. The upstream closes early or sends invalid or oversized headers

An application crash during response generation, a process restart, or malformed output can make Nginx report an invalid upstream response. Inspect the application log at the same timestamp as the Nginx error. Look for crashes, forced restarts, protocol-library errors, and output written before the response status line.

Large response headers are another specific case. Nginx Gateway Fabric documents “upstream sent too big header” as a 502 scenario and recommends increasing the response-header buffer or setting that buffer at the route level. Apply the smallest buffer change that accommodates the real headers, then retest; do not mask an application that is emitting unbounded cookies or metadata.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
location / {
    proxy_buffer_size 16k;
    proxy_buffers 4 16k;
    proxy_pass http://app:8000;
}

Use values appropriate to your deployment and measured headers. If buffering is disabled elsewhere in the gateway configuration, verify that the route’s response-header buffer is still sufficient.

8. An upstream group cannot select a usable server

When Nginx uses an upstream group, a 502 can occur before a request reaches an application. A full queue or failure to select a server within the configured queue timeout produces a gateway error. Check member health, DNS results, queue limits, and load-balancer selection settings.

upstream app_pool {
    least_conn;
    server app1.internal:8000;
    server app2.internal:8000;
    queue 100 timeout=10s;
}

server {
    location / {
        proxy_pass http://app_pool;
    }
}

Temporarily removing queueing or changing the client-facing error page does not restore capacity. First determine whether all members are unhealthy, the queue is too small, or the selection timeout is shorter than the expected burst.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Check the effective configuration before editing

Configuration mistakes often survive because an administrator edits a file that Nginx does not include. Dump the complete active configuration and inspect the matching server_name, listen, location, upstream, and proxy_pass directives.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
nginx -T

Look for a more specific location that wins over the block you changed, duplicate server names, an environment-generated include, or a different configuration file mounted into a container. Confirm the upstream scheme, hostname, port, and URI as one set; changing only the host while leaving an incompatible scheme or path can create a new 502.

Validate and reload safely

  1. Save the smallest change. Keep a copy of the previous working configuration and change only the endpoint, path, TLS setting, timeout, or buffer implicated by the log.
  2. Validate syntax. Run nginx -t. Do not reload if the test reports an error.
  3. Reload through the normal service mechanism. Use the service manager, container entrypoint, or orchestration method that owns the Nginx process rather than starting a second unmanaged process.
  4. Retest one known URL. Use the same host, path, method, and headers that reproduced the failure. If the endpoint requires authentication or a specific Host header, include them in the test.
  5. Watch both logs. Confirm the Nginx error log is quiet for that request and inspect the application log for the matching request.
  6. Verify the response source. Check that the status, headers, and body now come from the application and not from a cached error page or a different virtual host.
nginx -t
systemctl reload nginx
curl -i https://public.example.test/health

For a containerized deployment, run the equivalent configuration test inside the image and perform the reload or rollout through the container platform. A successful test against a temporary shell configuration does not prove that the production container loaded it.

A failure-phase decision guide

Evidence Most likely scope Next check
Connection refused immediately Backend process, port, bind address, or namespace Run ss -ltnp and direct curl from Nginx’s runtime
Connection timeout Routing, firewall, security policy, or unreachable host Resolve the name, test the route, and inspect network controls
TLS handshake failure HTTP/HTTPS scheme, SNI, certificate, trust, or TLS compatibility Test the TLS endpoint and compare the certificate name and port
Connected, then header timeout Slow or stuck application, dependency, or overloaded worker pool Compare upstream timing fields with application latency and logs
Invalid or oversized header Malformed output, early crash, or insufficient response-header buffer Inspect application output and adjust the measured buffer requirement
Queue or no-server selection error Unhealthy upstream group, full queue, or selection timeout Check member health, queue limits, and balancing configuration

Why common “fixes” fail

  • Refreshing the browser: repeats the same failed upstream request and provides no server-side evidence.
  • Changing only the public DNS record: does not correct an Nginx-to-backend route that is wrong inside the private network.
  • Raising every timeout: can turn a quick, diagnosable error into a pool of hanging connections.
  • Using 127.0.0.1 everywhere: breaks when Nginx and the application are in different containers or hosts.
  • Disabling TLS verification without diagnosis: may hide a certificate or SNI problem while weakening upstream security; it does not fix a plain-HTTP/TLS-port mismatch.
  • Replacing the 502 page: changes what clients see but leaves the upstream failure untouched.
  • Editing a single include file without checking nginx -T: risks changing an inactive configuration while the active server block continues to fail.

Preventing repeat 502 incidents

Keep a short record for every proxy route: the upstream address, scheme, port, expected path, network location, health-check URL, and owner of the application. This turns a vague “Nginx is down” alert into a concrete check that can be performed from the correct runtime.

  • Expose a lightweight health endpoint that confirms the process is listening without triggering expensive work.
  • Monitor the Nginx error log for connection refusal, timeout, handshake, invalid-header, and upstream-selection patterns separately.
  • Record $upstream_addr and the timing variables on routes where latency or failover matters.
  • Keep application, Nginx, and container-network changes versioned together so a port or service-name change cannot silently leave the proxy behind.
  • Test both the direct upstream URL and the public proxied URL after deployments, including the exact URI-prefix behavior used in production.
  • Set queue, buffer, and timeout policies from measured traffic and response characteristics rather than copying large values into every location.

The shortest reliable troubleshooting sequence

  1. Reproduce one 502 and capture the corresponding Nginx error-log line.
  2. Write down the upstream host, port, scheme, path, and failure phrase shown there.
  3. Run a direct request from the Nginx host, container, or pod to that exact endpoint.
  4. Fix the failed phase: start or rebind the service, correct DNS or networking, align HTTP versus HTTPS, repair the URI, address malformed or oversized headers, or restore upstream capacity.
  5. Run nginx -t, reload through the normal service path, and repeat the same request while watching both logs.
  6. Keep the smallest successful change and document the endpoint details for the next deployment.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.