ERR_EMPTY_RESPONSE (Chrome) / empty reply from server
The TCP (and maybe TLS) path opened — then the other side hung up without a single HTTP status line. Your browser has nothing to show except “empty response.”
What you see
This site can’t be reached
The webpage at https://example.com/ might be temporarily down or it may have moved permanently to a new web address.
ERR_EMPTY_RESPONSE
# curl says:
curl: (52) Empty reply from server
Firefox may say “the connection was reset” or show a blank failure; Safari often “cannot parse response.” Same family: the server (or something in the middle) closed without a usable HTTP message.
Empty response vs reset vs closed vs 520/502
| Symptom | What happened | Typical cause |
|---|---|---|
| ERR_EMPTY_RESPONSE / curl 52 | Connected; 0 HTTP bytes; then close | Process crash after accept, HTTP on HTTPS port, proxy ate the reply |
| ERR_CONNECTION_RESET | RST — peer aborted | Firewall RST, app abort; Node often ECONNRESET |
| ERR_CONNECTION_CLOSED | FIN without a complete response | Idle proxy close, half-open teardown |
| Cloudflare 520 | CF got empty/invalid origin reply | Same root causes behind the edge |
| 502 Bad Gateway | Proxy returns HTTP 502 | Upstream died; you still get a status page |
| SSL wrong version number | TLS client read non-TLS bytes | HTTP service on :443 or HTTPS on :80 |
| ERR_CONNECTION_REFUSED | Nothing accepted TCP | No listener — never an “empty” HTTP case |
Rule of thumb: empty response means “I got a socket, then silence.” Fix what accepts the connection and what should write the first status line — not DNS, and not “open another port” unless you are on the wrong one.
Frequent real causes
- App / nginx crash right after accept — worker segfaults, OOM-kill (exit 137), or the process exits before writing headers.
- Backend died behind a reverse proxy — proxy connected upstream, upstream closed with no bytes; some proxies pass that through as an empty reply instead of a clean 502.
- HTTP spoken to an HTTPS port (or the reverse) — client sends plain
GET /to a TLS listener (or TLS to a cleartext port). Sometimes wrong version number; sometimes the server just closes → empty response. - HTTP/2 / ALPN confusion — broken h2 SETTINGS, middleboxes that mishandle prior knowledge, or a CDN expecting h2 while the origin only does h1 poorly.
- Antivirus / TLS inspection — corporate middlebox terminates TLS, fails to talk to the real origin, and closes. Try another network or a clean curl from a server.
- Protocol mismatch on load balancers — LB health check expects HTTP but the pool speaks TLS only (or vice versa); intermittent empties when the bad node is chosen.
- Connection reuse after a dead keep-alive — rare; first request on a recycled socket gets FIN with no data. Retry often “fixes” it once — still worth checking proxy idle timeouts.
Diagnose with curl -v
# See whether TCP/TLS succeed and whether any HTTP bytes arrive:
curl -v --http1.1 https://example.com/ -o /dev/null
curl -v http://example.com/ -o /dev/null
# Watch for: Connected to … then immediately "Empty reply" / closing
# vs SSL errors (wrong port / wrong scheme)
# Hit the origin IP directly (bypass CDN) with the real Host:
curl -vI https://ORIGIN_IP/ -H "Host: example.com" -k --connect-timeout 5
# Force HTTP/1.1 vs HTTP/2 to spot h2 issues:
curl -v --http1.1 https://example.com/ -o /dev/null
curl -v --http2 https://example.com/ -o /dev/null
# On the server around the failure time:
sudo journalctl -u nginx -u your-app -n 120 --no-pager
sudo tail -n 80 /var/log/nginx/error.log
ss -lntup | grep -E ':80|:443'
If curl -v shows a completed TLS handshake and then EOF with no HTTP/1.1 status line, the listener accepted you and then failed to speak HTTP — that is the empty-response case. If TLS itself fails, fix scheme/port first (SSL wrong version / ERR_SSL_PROTOCOL_ERROR).
Fix checklist
- Confirm empty vs refused vs reset — refused → listener/port; reset → ECONNRESET path; empty → process accepted then sent nothing.
- Match scheme to port —
https://only to TLS listeners;http://to cleartext. Fix reverse-proxyproxy_pass http://vshttps://. - Reproduce with curl -v — capture whether TCP/TLS worked; try
--http1.1. - Read origin / proxy logs — crash, OOM, upstream prematurely closed, protocol errors at the failure timestamp.
- Stabilize the app behind the proxy — stop crash loops; ensure every request path writes a status line; prefer a deliberate 502 over a silent close.
- Check middleboxes — disable VPN/antivirus TLS inspection briefly; compare from a clean VPS.
- If Cloudflare sits in front — empty origin replies often surface as Error 520 to visitors; fix the origin the same way, then re-test orange-cloud.
# nginx: prefer a real upstream error over a silent close
# proxy_next_upstream error timeout http_502;
# proxy_http_version 1.1;
# Then: sudo nginx -t && sudo systemctl reload nginx
Related
ERR_CONNECTION_RESET · ECONNRESET / read ECONNRESET · Cloudflare Error 520 · 502 Bad Gateway · SSL wrong version number · localhost refused to connect · ERR_SSL_PROTOCOL_ERROR · Unexpected end of JSON input · Anvil HTTP status
Questions
What does ERR_EMPTY_RESPONSE mean?
The browser connected to the server but received no HTTP response bytes before the connection closed — Chrome shows net::ERR_EMPTY_RESPONSE; curl often says Empty reply from server.
How is empty response different from connection reset?
A reset is an abrupt RST (ERR_CONNECTION_RESET / ECONNRESET). Empty response usually means a clean-ish close after connect with zero HTTP bytes — often a crash or protocol mismatch.
How is this different from Cloudflare 520?
Same family of “no usable HTTP reply.” Through Cloudflare, visitors often see Error 520; direct-to-origin or without a branded gateway page you may see ERR_EMPTY_RESPONSE instead.
Can HTTP on an HTTPS port cause ERR_EMPTY_RESPONSE?
Yes. Sending cleartext HTTP to a TLS listener (or the reverse) can close with no HTTP status. Sometimes you get SSL wrong version number instead — both mean fix scheme/port.
How do I diagnose with curl?
Use curl -v (and try --http1.1). Check whether TCP/TLS complete and whether any HTTP status line appears before EOF.
What should I check on the server first?
Process listening on the port, app/nginx crash logs at the failure time, and that proxy_pass scheme matches the upstream (http vs https).
Can antivirus TLS inspection cause this?
Yes. Middleboxes that intercept TLS and fail open can close with an empty reply. Compare from another network or a clean server-side curl.
Published .