ERR_EMPTY_RESPONSE means the browser opened a TCP connection and sent its request, but the server closed the connection without returning a single byte — no status line, no headers, no body. The usual culprit is a crashed backend (php-fpm, Node.js, gunicorn), a proxy timeout, or a WAF that reset the connection. Check your web server logs for the exact cause.
This guide explains how ERR_EMPTY_RESPONSE differs from 502 and 504 errors, which server-side and client-side causes trigger it, how to trace the root cause through nginx and php-fpm logs, and what both administrators and regular users should do. It is written for site owners, DevOps engineers, and anyone who just wants the page to load again.
What ERR_EMPTY_RESPONSE means
This is a Chromium-level error (Chrome, Edge, Opera, Brave). It appears when the connection to the server was established and the request was sent, but the reply was empty: the server tore down the connection before sending an HTTP status line. Unlike a 500 or 404, there is no valid HTTP response at all — so the browser cannot render a normal server error page and shows its own message, "This page isn't working."
Causes of ERR_EMPTY_RESPONSE
An empty response is a symptom of a break at the transport layer. The source is almost always the server or an intermediate node, though occasionally the client is at fault. The main scenarios:
- Backend process crash. php-fpm, Node.js, gunicorn, or uWSGI died mid-request (segfault, OOM-killer, unhandled exception) and the connection closed with no reply.
- Memory exhaustion. The Linux OOM-killer terminates the interpreter process when RAM runs out. You will see
Out of memory: Killed processindmesg. - Proxy or upstream timeout. nginx/Apache acting as a reverse proxy drops the connection when the backend does not answer in time and buffering is configured so the client never receives a 504.
- WAF or rate limiting. Cloudflare, ModSecurity, or fail2ban can reset (RST) the connection instead of serving a block page — the browser reads that as an empty response.
- Broken HTTP/2 or gzip configuration. A failure during compression or stream multiplexing can close the connection without a proper response frame.
- Client-side causes. Corrupt browser cache, a conflicting extension, a VPN/proxy, or a faulty network driver can prevent the reply from arriving.
How it differs from 502 and 504
The key difference: with 502 and 504 the server (usually the proxy) still returns a valid HTTP response with a status code, whereas with ERR_EMPTY_RESPONSE there is no response at all. Compare the three situations:
| Error | Who returns it | Cause | Where to look |
|---|---|---|---|
| 502 Bad Gateway | Proxy (nginx/Apache) sends an HTTP response | Backend returned an invalid or empty reply that the proxy still processed | proxy error.log, backend logs |
| ERR_EMPTY_RESPONSE | Nobody — the connection closed with no HTTP response | Backend crashed/was killed, or the proxy reset the connection before sending a status | error.log, dmesg (OOM), php-fpm/node logs |
| 504 Gateway Timeout | Proxy sends an HTTP response | Backend did not answer within the timeout, but the proxy connection stayed alive | proxy error.log (upstream timed out) |
In short: 502 and 504 mean "the server replied that something is wrong," while ERR_EMPTY_RESPONSE means "the server silently hung up."
Server-side diagnosis
Start with the web server logs in real time, then replay the failing request through curl -v to see where the connection breaks.
tail -f /var/log/nginx/error.log
tail -f /var/log/php8.4-fpm.log
# in another window, replay the request with verbose output
curl -v https://example.com/slow-pageIf the backend is dying from lack of memory, it shows up in the system journal:
dmesg -T | grep -i 'out of memory'
journalctl -u php8.4-fpm --since '10 min ago'A typical nginx entry for an upstream break looks like this:
upstream prematurely closed connection while reading response header from upstream,
client: 203.0.113.5, server: example.com, request: "GET /report HTTP/1.1",
upstream: "fastcgi://unix:/run/php/php8.4-fpm.sock"That line says it plainly: php-fpm closed the connection early — look for the reason in the PHP log (fatal error, OOM, script timeout).
How to fix it on the server
Fix the root cause, not the symptom:
- Raise memory limits. Increase
memory_limitin PHP or--max-old-space-sizein Node.js if the OOM-killer is terminating the process. Add RAM or swap. - Align timeouts. The values of
fastcgi_read_timeout,proxy_read_timeoutin nginx andrequest_terminate_timeoutin php-fpm must be consistent so the proxy can return a 504 instead of dropping the connection. - Check the worker pool. Too small a
pm.max_childrenunder peak load causes refusals. Size the pool to the server's real memory. - Review WAF/rate-limit rules. Make sure ModSecurity, fail2ban, or Cloudflare are not resetting legitimate requests. Configure them to serve a 429 page instead of an RST.
- Disable problematic gzip/HTTP2 for a test. Temporarily remove compression or switch to HTTP/1.1 to isolate a multiplexing failure.
- Update PHP/Node/libraries. A segfault is often caused by a bug in an outdated extension (for example, opcache or imagick).
How to fix it as a user
If the site is not yours and you are not the administrator, try these in order:
- Clear the browser cache and cookies, then reload with
Ctrl+F5. - Open the site in incognito mode — this disables extensions.
- Temporarily turn off any VPN, proxy, or ad blocker.
- Flush the network stack:
ipconfig /flushdns(Windows) orsudo dscacheutil -flushcache(macOS). - Try a different browser or network (mobile data) — this tells you whether the fault is on the server or on your side.
If the page loads in incognito and on another device, the cause is almost certainly server-side, and the user can only wait for a fix or report it to the administrator.
How to check
To quickly see whether the server responds and which headers it returns, use our free HTTP header checker: if the server is alive you will see its status and headers; if there is no response, you have confirmed the problem is server-side. Our security scanner additionally reveals whether a WAF or a broken TLS configuration is cutting the connection. For the official HTTP reference see the MDN documentation, and for upstream response handling see the nginx documentation.
Related errors
ERR_EMPTY_RESPONSE often appears alongside other network failures. If the connection breaks differently, these breakdowns help: ERR_CONNECTION_RESET, ERR_CONNECTION_CLOSED, and for proxy responses 502 Bad Gateway and 504 Gateway Timeout.
Frequently Asked Questions
Is ERR_EMPTY_RESPONSE a problem with my computer or the server?
Most often the server: the backend crashed or the proxy reset the connection. But rule out the client — open the site in incognito, on another device, and on a different network. If the same error appears everywhere, the server is at fault and you can only wait for a fix or contact the site's administrator about it.
Why do I see an empty response instead of a 500 or 502 code?
A status code appears only if the server managed to build an HTTP response. With ERR_EMPTY_RESPONSE the process crashed or the connection was reset before the status line was sent, so there is no valid HTTP response at all — the browser has nothing to show except its own error.
How do I quickly find the cause on my own server?
Run tail -f on the nginx error.log and the php-fpm log, then replay the request with curl -v. A line about "upstream prematurely closed connection" points to the backend, while an "Out of memory" entry in dmesg points to a RAM shortage and the OOM-killer at work.
Can Cloudflare or a WAF cause ERR_EMPTY_RESPONSE?
Yes. WAF rules, Cloudflare, or fail2ban sometimes reset the connection with a TCP RST instead of serving a block page. Check the protective layer's logs and configure it to return a proper 403 or 429 response so the browser gets a clear status rather than an empty reply.
Does restarting the server help?
Restarting php-fpm or the web server clears the symptom temporarily if a process hung or exhausted memory. But without fixing the root cause — a memory leak, a small worker pool, or a code bug — the error returns under load. Find the source in the logs first, then adjust the configuration.