Skip to main content

Guides / Fix it: guides for the errors people actually hit

ERR_CONNECTION_RESET: causes and fixes

ERR_CONNECTION_RESET means a connection that had already opened was cut off abruptly with a TCP reset, usually by a firewall or filter, security software, or a server process that crashed, rather than closed normally by either side. The browser cannot tell which of these sent the reset, so you find the cause by testing from other networks and reading server logs.

What ERR_CONNECTION_RESET means

Unlike ERR_CONNECTION_REFUSED, which fires at the handshake, a reset arrives after the TCP handshake succeeded: during the TLS handshake, while the request is being sent, or partway through the response. Something on the path, or one of the endpoints, sends an RST segment that ends the connection on the spot. Chromium's error list defines the code (-101) as "a connection was reset (corresponding to a TCP RST)". The server, a load balancer, a firewall, and software on your own computer can all send one, and the browser sees the same RST whichever sent it.

A normal TCP close is a FIN exchange in each direction, which lets both sides finish sending what they had queued. An RST skips that and discards whatever was in flight, which is why a reset partway through a download or a long API response leaves a truncated result. RFC 9293 describes when TCP itself sends a reset. Two rules matter most here: a segment that arrives for a connection that no longer exists gets a reset, and a host that closes a connection while received data is still unread "SHOULD send a RST to show that data was lost." The second rule explains a common upload failure: a server that rejects an upload and closes the socket before reading the whole body resets the client, which then never sees the server's error page.

How the error appears

Chrome shows "This site can't be reached" with "The connection was reset" and ERR_CONNECTION_RESET, sometimes after part of the page has already rendered. Firefox shows "The connection was reset". curl reports it with exit code 56:

curl -sS -o /dev/null http://example.com/export.csv
curl: (56) Recv failure: Connection reset by peer

Over HTTPS the exact wording depends on the curl and TLS library versions, but the exit code tells you when the reset hit. Code 35 means it happened during the TLS handshake, which points toward network filters or TLS inspection. Code 56 means it happened while receiving data afterward, which points toward crashes, size limits, and timeouts. A reset that happens consistently at the same byte count or the same number of seconds into a request points to a fixed limit on the path, not a random network glitch.

ERR_CONNECTION_RESET vs similar errors

Chrome shows all of these under the same "This site can't be reached" heading, so the code underneath is what tells them apart. The rows follow the order in which a page load meets them, from the DNS lookup to the first byte of the response. The numbers are Chromium's internal error codes.

ErrorWhat happened at the network or protocol levelWhere to look first
ERR_NAME_NOT_RESOLVED (-105)The DNS lookup returned no usable IP address, so no connection was attempted.The domain's DNS records and the resolver the device uses.
ERR_ADDRESS_UNREACHABLE (-109)The operating system or a router reported that there is no route to the IP address.Routing on the client side: VPN routes, the local network, IPv6 setup.
ERR_CONNECTION_TIMED_OUT (-118)The SYN went out and nothing came back, neither SYN-ACK nor RST, until the client gave up.Firewalls and security groups that drop packets, whether the host is up, and the IP address DNS returns.
ERR_CONNECTION_REFUSED (-102)The SYN reached the host and was rejected right away, usually with an RST.Whether a process listens on that port and address, and firewall REJECT rules.
ERR_CONNECTION_RESET (-101)The connection was open, then an RST ended it during the TLS handshake or the transfer.Proxy, WAF, and application logs at that moment; antivirus, VPN, or filtering on the client's network.
ERR_EMPTY_RESPONSE (-324)The connection opened and the request went out, but the server closed the connection without sending any data.Server and proxy error logs for crashed workers or connections closed on purpose (nginx's return 444).

What causes ERR_CONNECTION_RESET

  • A firewall, IPS, or WAF ends the connection mid-stream. Rules that match on content or request rate act after the handshake, and some are set to end the connection with a reset rather than return an error page.
  • Network filtering by server name. Filters that read the site name from the TLS handshake, including some corporate, school, and national filters, block sites by injecting a reset. Some ISPs and mobile carriers also reset connections as part of traffic management.
  • TLS inspection by antivirus software or a corporate proxy. HTTPS scanning that fails on a particular site or a large response often resets the connection rather than failing with a clear message.
  • A server process dies mid-request. An application crash, an out-of-memory kill, or a worker restart during a deploy closes the sockets the process held. The client sees a reset or, if nothing had been sent and the close was clean, ERR_EMPTY_RESPONSE.
  • An upload larger than the server accepts. The server answers with an error and closes the connection while the browser is still sending the body, and the unread data triggers a reset.
  • Idle timeouts in load balancers and NAT devices. A connection idle for longer than the device's timeout is forgotten, and the next packet on it gets a reset. WebSockets, server-sent events, and long polling hit this most.
  • Path MTU problems on VPNs, tunnels, and PPPoE links. When the ICMP messages that path MTU discovery depends on are blocked, full-size packets are lost while small ones get through. The handshake succeeds, the transfer stalls, and depending on which side gives up first the browser shows a reset or a timeout.

Server-side causes and configuration

When the reset reaches the browser, it came from whatever holds the browser's own connection or sits on its path: the web server, the load balancer or CDN edge in front of it, a network device, or software on the visitor's machine. A backend that resets a reverse proxy usually turns into a 502 Bad Gateway for the visitor instead, so the server-side search starts at the edge and works inward.

Crashed or killed workers

# Kernel out-of-memory kills in the last hour
sudo journalctl -k --since "1 hour ago" | grep -i -E "out of memory|killed process"

# Restarts and crashes of a systemd service
sudo journalctl -u myapp --since "1 hour ago" --no-pager

PHP-FPM logs crashed children in its own log, for example WARNING: [pool www] child 2817 exited on signal 11 (SIGSEGV) after 12.481935 seconds from start. Match the timestamps against the moment the reset happened.

Upload size limits

nginx rejects request bodies larger than client_max_body_size (1 MB by default) with a 413 error, and its documentation warns that browsers cannot correctly display that error; visitors often get a reset instead. Raise the limit where uploads happen:

# nginx: http, server, or location context
client_max_body_size 50m;

# Apache: limit in bytes (52428800 = 50 MiB)
LimitRequestBody 52428800

Keep-alive timeouts between a proxy and its backend

A reverse proxy keeps idle connections to the backend open for reuse. If the backend closes an idle connection first, the proxy can send the next request onto a connection the backend has just closed and get a reset back. nginx then logs recv() failed (104: Connection reset by peer) while reading response header from upstream, and Apache logs (104)Connection reset by peer: ... AH01102: error reading status line from remote server. The visitor usually sees an intermittent 502 rather than a reset. The rule is that the backend's idle timeout must be longer than the proxy's:

upstream app {
    server 127.0.0.1:3000;
    keepalive 16;
    keepalive_timeout 30s;   # shorter than the backend's idle timeout
}

server {
    listen 80;
    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;          # needed before nginx 1.29.7
        proxy_set_header Connection "";  # needed before nginx 1.29.7
    }
}

Node.js closes idle keep-alive connections after 5 seconds by default, far shorter than the 60-second default of nginx's upstream keepalive_timeout, so raise it above whatever the proxy uses:

const http = require('node:http');
const server = http.createServer((req, res) => res.end('ok'));
server.keepAliveTimeout = 65000; // default is 5000 ms
server.listen(3000);

Load balancers and long-lived connections

Layer 4 load balancers and NAT gateways track every connection and forget idle ones. AWS documents that its Network Load Balancer stops tracking a TCP connection after 350 seconds without data by default, and that if either side sends data after that, the client receives a TCP RST. Keep long-lived connections busy with WebSocket ping frames or application heartbeats sent more often than the shortest idle timeout on the path. Plain TCP keepalive helps only if you lower its timer, because Linux waits 2 hours by default (net.ipv4.tcp_keepalive_time) before sending the first probe.

Deliberate resets and Docker

nginx's reset_timedout_connection on; makes nginx reset timed-out connections, and connections closed with its non-standard code 444, instead of closing them normally. With it off, a return 444; usually shows up as ERR_EMPTY_RESPONSE. On a Docker host, curl: (56) Recv failure: Connection reset by peer against a published port from the host itself usually means the app inside the container listens on 127.0.0.1 or on another port than the -p mapping says; the ERR_CONNECTION_REFUSED guide covers that mapping.

How it looks from the outside

  • Reset from every location at the same point. A size limit, a timeout, or a crash on that URL at the server or its edge. Reproduce with the exact request and read the logs for that moment.
  • Reset from one country or network only. Filtering on that network, or a broken edge node serving that region.
  • Intermittent resets from random locations. Crashing workers, one unhealthy server behind a load balancer, or idle-timeout races.
  • Reset during the TLS handshake only. TLS inspection or name-based filtering on that path, or the TLS terminator itself. Plain HTTP to the same host often works.
  • Fine from every checkpoint, reset only for you. Antivirus, a VPN, a proxy, or your ISP.

The HTTP checker sends the request from many locations at once and shows the result from each, which separates a site-wide reset from one tied to a single network.

How to fix ERR_CONNECTION_RESET

If you are a visitor

  1. Try another network, such as mobile data instead of Wi-Fi. If the site loads there, the cause is on your device or your network.
  2. Turn off HTTPS scanning in your antivirus, usually listed under "web protection" or "SSL/TLS scanning," and retry. If that fixes it, add the site to an exclusion list rather than leaving scanning off.
  3. Disable any VPN or proxy and reload. If the reset stops, the VPN or proxy is intercepting or mishandling the connection.
  4. Restart your router or modem to clear stale connection state.
  5. On Windows, reset Winsock. Run netsh winsock reset in an administrator Command Prompt and restart. It can remove network hooks left behind by uninstalled security or VPN software.
  6. Close Chrome's open connections. Open chrome://net-internals/#sockets and click "Flush socket pools", then reload.
  7. Test the path MTU if you are on a VPN or a mobile hotspot. Run the command for your system (Windows, Linux, macOS, in that order):
    ping -f -l 1472 example.com
    ping -M do -s 1472 example.com
    ping -D -s 1472 example.com
    If the ping fails with a "needs to be fragmented" or "message too long" error, or gets no reply, lower the size until it passes; that size plus 28 is your path MTU. Setting the VPN or network interface MTU to that value can stop the resets.

If you run the site

  1. Reproduce and measure. Note where the reset hits with curl -sS -o /dev/null -w '%{size_download} bytes %{time_total}s\n' https://example.com/path. A repeatable byte count or duration points at a limit.
  2. Check application and kernel logs for a crash, an out-of-memory kill, or a restart at that moment.
  3. Review WAF and IPS logs. A rule that resets connections matching certain payloads or rates looks identical to a network fault until you check the security log.
  4. Check size limits and timeouts on every hop: client_max_body_size, load balancer idle timeouts, and the keep-alive settings above.
  5. Reload safely after each change: sudo nginx -t && sudo systemctl reload nginx validates the configuration before it takes effect.

How to prevent ERR_CONNECTION_RESET

A reset that appears only under load, only for large responses, or only from certain networks rarely shows up in a quick manual check. Ongoing HTTP monitoring repeats the request on a schedule from 300+ checkpoints in 158 cities, so an intermittent or regional reset pattern becomes visible, and HostTracker alerts by email, SMS, voice call, Slack, Telegram and more as soon as checks start failing.

Frequently asked questions

Does ERR_CONNECTION_RESET mean I was hacked?

No. It almost always points to a network device, a firewall rule, antivirus interception, or a server-side crash, not to an attack on your device.

Why do I get ERR_CONNECTION_RESET when uploading a file?

The file is probably larger than the server accepts. The server rejects the body, closes the connection before reading all of it, and the browser gets a reset instead of the error page. The site owner needs to raise the upload limit, such as nginx's client_max_body_size.

Why does this only happen with large file downloads?

Large transfers run longer and move more data, so they are more likely to cross a proxy timeout, a size limit on a firewall or load balancer, or a filter that inspects content. Any of these can end a connection mid-stream that a small request would finish first.

Why does a WebSocket or long request drop after a few idle minutes?

A load balancer, NAT device, or proxy on the path forgot the idle connection, and the next packet got a reset. Send pings or heartbeats more often than the shortest idle timeout on the path.

Can my own antivirus cause this?

Yes. HTTPS scanning that intercepts and re-encrypts TLS traffic sometimes fails on specific sites or large responses and resets the connection instead of passing it through.

Is a reset worse than a timeout?

Not inherently. A reset means something actively ended the connection, which is often easier to diagnose than a timeout, where nothing comes back and you cannot tell whether the packets arrived at all.

Why does the reset happen at the same point every time?

A consistent byte count or elapsed time before the reset usually points to a fixed limit, such as a proxy timeout, a maximum body size, or an idle timeout, rather than a random fault.

Can a mobile carrier reset my connections?

Some carriers reset connections as part of network management, particularly on congested cells or for high-bandwidth transfers like video. If the same request works reliably over Wi-Fi but resets on mobile data, the carrier is a likely cause.

Sources and further reading

Check it now

Run the free check against your own site - no account needed.

HTTP check

Monitor this permanently

Get alerted the moment it breaks: HostTracker checks from 300+ locations and notifies you by email, SMS, Slack, Telegram and more.

HostTracker features

More in this section: Fix it: guides for the errors people actually hit