Connection Reset
Peer
Internet Protocol
Network Troubleshooting
Error Messages

What does connection reset by peer mean?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

"Connection reset by peer" means the remote side of a TCP connection abruptly closed the connection by sending a RST (reset) packet instead of going through the normal TCP shutdown sequence. In practical terms, the server (or client) on the other end forcibly terminated the connection, and your application received an error instead of the data it expected.

How TCP Connections Normally Close

To understand a reset, you first need to understand a normal close. TCP connections terminate gracefully with a four-step FIN handshake:

  1. Side A sends a FIN packet ("I'm done sending")
  2. Side B acknowledges the FIN
  3. Side B sends its own FIN ("I'm done too")
  4. Side A acknowledges

This orderly shutdown lets both sides finish processing any remaining data. A connection reset skips all of this. The peer sends a single RST packet that says "this connection no longer exists, stop immediately."

What Triggers a RST Packet

At the TCP level, a RST packet is sent in these situations:

 
1SYN to a closed port          -> RST from the receiver
2Data sent to a half-open conn -> RST from the receiver
3Application calls close()     -> RST if unread data in buffer
4Firewall intercepts packet    -> RST injected into the stream

Here is what these look like in application code:

Python:

python
1import socket
2
3try:
4    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
5    sock.connect(('api.example.com', 443))
6    sock.sendall(b'GET / HTTP/1.1\r\nHost: api.example.com\r\n\r\n')
7    data = sock.recv(4096)
8except ConnectionResetError as e:
9    print(f"Connection reset by peer: {e}")
10finally:
11    sock.close()

Java:

java
1try {
2    Socket socket = new Socket("api.example.com", 443);
3    OutputStream out = socket.getOutputStream();
4    out.write("GET / HTTP/1.1\r\nHost: api.example.com\r\n\r\n".getBytes());
5    InputStream in = socket.getInputStream();
6    int data = in.read();  // throws if reset
7} catch (SocketException e) {
8    System.out.println("Connection reset: " + e.getMessage());
9}

curl:

bash
1curl -v https://api.example.com/endpoint
2# * Recv failure: Connection reset by peer
3# * Closing connection 0
4# curl: (56) Recv failure: Connection reset by peer

Common Causes and How to Identify Them

CauseSymptomsHow to Confirm
Server crashed or restartedSudden reset during active requestCheck server uptime logs, look for OOM kills
Server-side timeoutReset after idle periodCompare idle time against server's keepalive_timeout
Load balancer dropped connectionIntermittent resets under loadCheck LB idle timeout settings (often 60s on AWS ALB)
Firewall or IDS killed connectionResets on specific request patternsPacket capture shows RST from intermediate IP
Server rejected TLS handshakeReset during SSL negotiationopenssl s_client -connect host:port fails
Server's listen backlog fullReset on new connections during spikenetstat -s shows listen queue overflows
Client sent data after server closedReset on write after partial readApplication logs show incomplete reads

Debugging Step by Step

Step 1: Capture the packets

The most reliable way to diagnose a connection reset is to look at the actual packets:

bash
1# Linux/macOS - capture traffic to a specific host
2sudo tcpdump -i any host api.example.com -w reset_debug.pcap
3
4# Then reproduce the error and open in Wireshark
5wireshark reset_debug.pcap

Look for the RST packet and check what came immediately before it. The packet before the RST usually tells you the cause.

Step 2: Check server-side logs

bash
1# Nginx
2tail -f /var/log/nginx/error.log | grep "reset"
3
4# Apache
5tail -f /var/log/apache2/error.log | grep "reset\|RST"
6
7# Application server (e.g., Gunicorn)
8tail -f /var/log/gunicorn/error.log

Step 3: Check connection limits and timeouts

bash
1# Linux - check current connections
2ss -s
3
4# Check kernel connection limits
5sysctl net.core.somaxconn
6sysctl net.ipv4.tcp_max_syn_backlog
7
8# Check file descriptor limits
9ulimit -n

Step 4: Test with different tools

bash
1# Test basic TCP connectivity
2nc -zv api.example.com 443
3
4# Test with explicit timeout
5curl --connect-timeout 5 --max-time 30 -v https://api.example.com/
6
7# Test TLS specifically
8openssl s_client -connect api.example.com:443

How to Handle Connection Resets in Your Code

The right response depends on whether the operation is idempotent (safe to retry).

Python with retry logic:

python
1import time
2import requests
3from requests.adapters import HTTPAdapter
4from urllib3.util.retry import Retry
5
6session = requests.Session()
7retries = Retry(
8    total=3,
9    backoff_factor=0.5,          # 0.5s, 1s, 2s
10    status_forcelist=[502, 503],
11    allowed_methods=["GET", "PUT"],  # only retry idempotent methods
12)
13session.mount("https://", HTTPAdapter(max_retries=retries))
14
15try:
16    response = session.get("https://api.example.com/data")
17except requests.exceptions.ConnectionError as e:
18    print(f"All retries failed: {e}")

Node.js with retry:

javascript
1async function fetchWithRetry(url, maxRetries = 3) {
2  for (let attempt = 1; attempt <= maxRetries; attempt++) {
3    try {
4      const response = await fetch(url);
5      return response;
6    } catch (err) {
7      if (err.cause?.code === 'ECONNRESET' && attempt < maxRetries) {
8        const delay = Math.pow(2, attempt) * 100;
9        console.log(`Connection reset, retrying in ${delay}ms...`);
10        await new Promise(r => setTimeout(r, delay));
11        continue;
12      }
13      throw err;
14    }
15  }
16}

Connection Reset vs. Other Network Errors

ErrorWhat It MeansTCP Behavior
Connection reset by peerRemote side sent RSTAbrupt close, no FIN handshake
Connection refusedNo process listening on portRST in response to SYN
Connection timed outNo response at allNo packets received
Broken pipeWrite to a closed connectionLocal side detects closed socket
EOF / Connection closedRemote side sent FINGraceful close

Understanding these distinctions matters because the fix is different for each. A "connection refused" means the service is not running. A "connection reset" means it was running but dropped you.

Common Pitfalls

  • Retrying non-idempotent requests. If a POST request gets reset, the server may have already processed it. Blindly retrying could create duplicate records. Only retry idempotent operations (GET, PUT, DELETE) automatically.
  • Ignoring keep-alive mismatches. If your client holds a connection open for 120 seconds but the server's keep-alive timeout is 60 seconds, the server will close the connection and your next request on that connection gets a reset. Set client timeouts to be shorter than server timeouts.
  • Blaming the network when it's the application. A reset that consistently happens at the same point in a request (e.g., after sending a specific header or payload) usually indicates the server is rejecting the request, not a network problem.
  • Not checking intermediate proxies. Load balancers, CDNs, and reverse proxies all have their own idle timeout settings. An AWS ALB defaults to 60 seconds, and if your backend takes longer, the ALB resets the client connection.

Summary

  • "Connection reset by peer" means the remote side sent a TCP RST packet, forcibly closing the connection.
  • Common causes include server restarts, load balancer timeouts, firewall rules, and listen queue overflows.
  • Use tcpdump or Wireshark to capture packets and identify the exact cause from the packet preceding the RST.
  • Implement retry logic with exponential backoff for idempotent operations.
  • Distinguish between connection resets, refused connections, timeouts, and broken pipes, because the fix is different for each.
  • Check intermediate infrastructure (load balancers, CDNs, proxies) for timeout mismatches, not just the origin server.

Course illustration
Course illustration

All Rights Reserved.