BugMojoBugMojoBugMojo
FeaturesPricingBlogHelpAbout
Add to ChromeLog inGet started
BugMojoBugMojo

Bug reports that actually help fix bugs — capture, replay, share.

A product of Softech Infra.

Product

  • Features
  • Pricing
  • Browser extension
  • Get started
  • Log in

Resources

  • Help & guides
  • Blog
  • Compare
  • Glossary

Company

  • About
  • Contact
  • Security
  • Privacy
  • Terms
  • Sitemap
© 2026 BugMojo. All rights reserved.
AllGuidesEngineeringPlaybooksCompareGlossaryAlternativesBy roleBug tracking by framework
  1. Home
  2. Blog
  3. Guides
  4. How to Fix a 502 Bad Gateway Error
Guide

How to Fix a 502 Bad Gateway Error

A 502 is not your browser's fault, and it usually isn't the gateway's either. It means a proxy got a broken answer from the server behind it. Here is how to find which layer failed and fix it.

Hrishikesh BaidyaHrishikesh Baidya·Jul 16, 2026·9 min read
Guides
Isometric line-art pipeline of a browser request passing through a proxy or CDN to an upstream server that returns a bad response, the upstream node cracked, lime on a dark canvas
TL;DR
  • What it means: a server acting as a gateway or proxy forwarded your request to an upstream server and got back an invalid or empty response.
  • Where the failure is: between the gateway and your app — not between your browser and the gateway. The intermediary is working; the thing behind it isn't.
  • Common causes: the upstream app crashed, restarted, ran out of memory, timed out, was pointed at the wrong address/port, or closed the connection mid-response.
  • Find it fast: read the proxy's error log and the app's log, then curl the upstream directly to isolate which layer is broken.

A 502 Bad Gateway is one of the most misread errors on the web, because the machine that reports it is almost never the machine that's broken. The status comes from a middleman — a reverse proxy, a load balancer, a CDN, or an API gateway — that accepted your request just fine, tried to hand it off to the real application behind it, and got an answer it couldn't use. Understanding that one fact turns a vague "the site is down" into a precise question: which hop failed, and why?

What a 502 actually means

A 502 Bad Gateway is returned by a server acting as a gateway or proxy when it receives an invalid or empty response from the upstream server it forwarded the request to. The gateway is reachable and working; the application behind it is what failed. The failing hop is between the proxy and your app, never between the browser and the proxy.

Picture the request as a relay. Your browser talks to the edge — say Cloudflare or an Nginx reverse proxy. That edge doesn't run your application; it forwards the request to an upstream: your Node process, a container, a Kubernetes service, a PHP-FPM pool. When the upstream replies with something the proxy can't parse — a truncated response, an empty body, a dropped connection, garbage bytes — the proxy has no valid answer to relay back. So it synthesises one: 502 Bad Gateway. The code is the proxy's way of saying "I did my job, but the server I depend on gave me nonsense."

This is the single most useful mental model for debugging a 502: the error is a message about the upstream, generated by the gateway. Everything that follows is about locating which upstream, and figuring out what it sent instead of a real response.

The common causes

In rough order of how often they turn up in real incidents:

  • The upstream app is down, crashed, or restarting. A deploy is mid-rollout, the process exited, or the container is still booting. The proxy connects to a port with nothing listening — or something that dies mid-response.
  • The upstream timed out. If the proxy gives up waiting you usually get a 504 Gateway Timeout instead, but some proxies surface a slow, half-closed connection as a 502. The distinction matters — more on that below.
  • The process died from memory pressure (OOM). The kernel's OOM killer terminates your app mid-request; the proxy sees the socket close with no valid response.
  • Wrong upstream address or port in the proxy config. A proxy_pass pointing at 127.0.0.1:3000 when the app now listens on :8080 produces a 502 on every request.
  • Malformed responses or a closed connection. The app writes invalid headers, sends a body that doesn't match its Content-Length, or resets the connection before finishing.
  • TLS or handshake failures between proxy and upstream. If the proxy speaks HTTPS to the upstream and the certificate, protocol, or SNI doesn't match, the handshake fails and the proxy reports a bad gateway.
  • Scaling and cold starts. Serverless functions and autoscaled pods that are still spinning up can refuse or drop connections during the cold-start window.

How to diagnose it

Debugging a 502 is a process of elimination across the relay. The goal is to find the exact hop that broke, and you do that by testing each link independently instead of guessing.

1. Confirm the upstream is actually running and healthy. Before touching the proxy, check that your application process is alive, listening on the expected port, and answering its own health check. A surprising share of 502s are simply an app that isn't running.

2. Read both logs — the proxy's and the app's. The proxy log tells you what the gateway saw; the app log tells you what the upstream did (or that it never got the request at all). For Nginx the relevant file is the error log, which records the upstream address and the reason the connection failed.

read-nginx-error-log.sh
# Watch Nginx's error log while you reproduce the request
tail -f /var/log/nginx/error.log

# A classic 502 line looks like this — note the upstream address and reason:
# connect() failed (111: Connection refused) while connecting to upstream,
#   upstream: "http://127.0.0.1:3000/", host: "app.example.com"
#
# "Connection refused" => nothing is listening on that port (app down / wrong port)
# "upstream prematurely closed connection" => the app died mid-response (often OOM)

3. Curl the upstream directly to bypass the proxy. This is the fastest way to isolate the failing layer. If you hit the application's own address and it answers correctly, the proxy or its config is at fault. If it fails or hangs the same way the proxy does, the problem is the app itself.

curl-the-upstream-directly.sh
# Hit the app directly, skipping the reverse proxy / load balancer entirely.
# Run this from the proxy host (or wherever the proxy connects from).
curl -i http://127.0.0.1:3000/health

# Healthy upstream => the app is fine; suspect the proxy config or the hop to it.
#   HTTP/1.1 200 OK
#   content-type: application/json
#
# Connection refused => the app isn't listening there (down, crashed, wrong port).
#   curl: (7) Failed to connect to 127.0.0.1 port 3000: Connection refused

# Also inspect ONLY the headers of the public URL to see which proxy answered:
curl -sI https://app.example.com/ | grep -iE 'server|via|cf-ray|x-served-by'

4. Check the proxy's timeout and upstream settings. If the app is slow rather than dead, the fix may be a larger read timeout — or, better, making the app faster. Here is the Nginx block that governs both where requests go and how long the proxy waits before declaring failure.

nginx.confnginx
upstream app_backend {
  server 127.0.0.1:3000;   # must match where your app actually listens
}

server {
  location / {
    proxy_pass http://app_backend;

    # How long the proxy waits for the upstream at each stage.
    proxy_connect_timeout 5s;   # time to establish the TCP connection
    proxy_send_timeout    30s;  # time to send the request
    proxy_read_timeout    60s;  # time to read the response (raise for slow apps)
  }
}

5. Look at recent deploys. If a 502 started at a specific minute, correlate it with a deploy, a config change, a scaling event, or a dependency (database, cache) going down. The timeline is often the whole diagnosis: something changed, and the upstream stopped answering cleanly right after.

Tip

When a 502 only happens for some users or some routes, the response headers on the failed request are gold. A captured request shows exactly which host returned the 502 and what its headers say — a CF-RAY header points at Cloudflare, a Via or Server header names the proxy — so you know which layer to open the logs on instead of guessing between the CDN, the load balancer, and the app.

502 vs 504 vs 503 vs 500

These four codes get conflated constantly, but each points you at a different failure and a different fix. Getting the distinction right saves you from debugging the wrong layer.

  • 502 Bad Gateway — the gateway got a bad response from the upstream. The app answered, but with something invalid or empty (or the connection dropped). Fix the upstream's response.
  • 504 Gateway Timeout — the gateway got no response in time. The upstream is too slow or hung. Speed up the app or raise the timeout deliberately. The difference from a 502 is response-vs-no-response: broken answer versus no answer.
  • 503 Service Unavailable — the server is temporarily unable to serve the request: overloaded, in maintenance, or a load balancer with no healthy backends to route to. It's a capacity or availability signal, not a broken hop.
  • 500 Internal Server Error — the application itself threw an unhandled error while producing a response. This is a bug in your code or a failed dependency inside the app, not a proxy problem. If you're chasing a 500, the guide on fixing a 500 Internal Server Error is the right place to start.

A quick way to remember it: 500 is the app failing on its own, while 502, 503, and 504 are all reported by something in front of the app. Among those three, 502 is a bad answer, 504 is no answer in time, and 503 is "not right now." If you want the full map of every status class, the HTTP status codes explained reference lays them out side by side.

Fixing it for good

Once you've isolated the failing hop, the fix follows directly from the cause. If the app was down or crashing, the real work is keeping it up: add a process supervisor or health-checked orchestration that restarts it, and fix whatever killed it — often an out-of-memory condition or an unhandled crash. If the OOM killer is involved, either raise the memory limit or fix the leak; a 502 that recurs on a schedule is frequently memory that climbs until the process is reaped.

If the config was wrong, align the proxy's proxy_pass and upstream block with where the app actually listens, and treat that config as something to test in CI rather than edit by hand in production. If the app was merely slow, resist the urge to just crank proxy_read_timeout to a huge number — that trades a fast 502 for a slow-loading page and hides the real regression. Profile the slow path, and raise the timeout only as a deliberate allowance for work that genuinely takes that long. And if cold starts are the culprit, warm the pool: keep a minimum number of instances alive, or add readiness checks so the load balancer doesn't route to a pod that hasn't finished booting.

Key takeaway

The honest takeaway: a 502 is a pointer, not a diagnosis. It tells you a gateway got a broken answer from the server behind it — so stop debugging the browser and the proxy, and go look at the upstream. Read both logs, curl the upstream directly to isolate the hop, and check what changed. The fix is almost always on the application the proxy was trying to reach, not on the proxy that reported the error.

⁓ ⁓ ⁓
See which server actually returned the 502

Install the free BugMojo extension and capture the exact failed request — its host, status, and response headers — so you know whether the CDN, the load balancer, or your app produced the 502 instead of guessing.

Install the free extension

Frequently asked questions

Frequently asked questions

Sources

  1. 502 Bad Gateway — MDN reference: the server, while acting as a gateway or proxy, received an invalid response from the upstream server — MDN Web Docs (2026)
  2. 504 Gateway Timeout — MDN reference: the gateway did not get a response in time from the upstream server — MDN Web Docs (2026)
  3. HTTP response status codes — MDN reference: the full list of 1xx–5xx codes and what each class signals — MDN Web Docs (2026)
  4. RFC 9110: HTTP Semantics — the normative definitions of 502, 503, and 504 gateway status codes — IETF RFC 9110 (2022)
Share:
Hrishikesh Baidya
Hrishikesh Baidya· Chief Technology Officer

Hrishikesh Baidya is the CTO at Softech Infra. He is drawn to architecture that is invisible — systems that simply work — and leads the engineering behind BugMojo.

On this page

  • What a 502 actually means
  • The common causes
  • How to diagnose it
  • 502 vs 504 vs 503 vs 500
  • Fixing it for good

Get bug-tracking insights, weekly.

Engineering deep-dives, QA playbooks, and honest tool comparisons. No spam — unsubscribe in one click.