What it means: The other end, or something between, abruptly reset an open TCP connection while your code used it.
Free online tool — ping & port checker: instant results, no signup.
Pings your host from our server, so you see whether it answers from outside your network.
ECONNRESET is the operating system error «Connection reset by peer» (errno 104 on Linux). The Node.js docs describe it as: «A connection was forcibly closed by a peer. This normally results from a loss of the connection on the remote socket due to a timeout or reboot. Commonly encountered via the http and net modules.» (Node.js common system errors). Typical forms:
Error: read ECONNRESET
at TCP.onStreamRead (node:internal/stream_base_commons) { errno: -104, code: 'ECONNRESET', syscall: 'read' }
Error: socket hang up { code: 'ECONNRESET' }«socket hang up» is the http client's variant: the http docs list an 'error' event with message 'Error: socket hang up' and code 'ECONNRESET' when the connection closes before a response arrives. Python reports the same condition as ConnectionResetError: [Errno 104] Connection reset by peer, curl as Recv failure: Connection reset by peer.
It is not a refused connection: ECONNREFUSED happens before the connection exists. ECONNRESET means the connection was open and then torn down with a TCP RST.
| Cause | Pattern | Fix |
|---|---|---|
| Reused keep-alive socket the server already closed | Sporadic, after a few seconds of idle, first request after a pause | Client idle timeout shorter than the server's; retry idempotent calls |
| Load balancer or proxy idle timeout | Fails at a fixed duration (60 s, 100 s, 350 s ...) | Align timeouts; send keep-alive probes on long streams |
| Server process crashed or was killed mid-request | Matches restarts, OOM kills or deploys | Fix the crash; drain connections on deploy |
| Server rejects the request body | Large uploads; server answers 413 and closes | Raise the body limit or send smaller chunks |
| Firewall or IDS resets the flow | Specific hosts, ports or payloads only | Find the device that sends the RST with tcpdump |
| TLS mismatch at the far end | Reset right after connect, during the handshake | Check protocol and SNI with openssl s_client |
The first row is the classic Node.js case. Since Node.js 19 the default http agent uses keep-alive with a 5-second timeout, and a Node.js server closes idle keep-alive sockets after server.keepAliveTimeout, which defaults to 5000 ms (http docs). When the client picks a pooled socket at the same moment the server closes it, the request is written into a closing connection and fails with ECONNRESET or «socket hang up».
Every hop has its own idle timeout, and the rule is the same at each one: the side that keeps a connection open longer must be upstream. If a load balancer keeps idle connections to your Node.js app for 60 seconds while the app closes them after 5, the balancer will occasionally send a request into a socket the app just closed, and clients see 502 errors or resets. Raise the app's timeouts above the balancer's:
const server = http.createServer(app);
server.keepAliveTimeout = 65_000; // longer than the balancer's idle timeout
server.headersTimeout = 66_000; // keep it above keepAliveTimeoutIn nginx in front of Node.js, a reset from the app appears in the error log as recv() failed (104: Connection reset by peer) while reading response header from upstream and the client gets a 502. Related proxy-side message: upstream prematurely closed connection.
code, syscall and the remote address, and record whether the socket was reused:req.on('socket', (s) => console.log('reused:', req.reusedSocket));
req.on('error', (e) => console.error(e.code, e.syscall, e.message));req.reusedSocket is true and the error is ECONNRESET, but only for idempotent requests (GET, PUT, DELETE), never a payment POST.new http.Agent({ keepAlive: false }).journalctl -u app --since '-1h', kubectl get pods restart counts, dmesg -T | grep -i oom).tcpdump -ni any 'host 203.0.113.10 and tcp[tcpflags] & tcp-rst != 0'A reset that the server never sent was injected by a firewall or middlebox.openssl s_client -connect api.example.com:443 -servername api.example.com.# Hammer the endpoint with pauses around the keep-alive timeout
for i in $(seq 1 20); do curl -sS -o /dev/null -w '%{http_code} ' https://api.example.com/health; sleep 5; done
# 200 200 200 ... with no 'Connection reset by peer'Watch the error rate in application logs for a day: keep-alive races are rare per request but steady under load. To confirm the host and port answer from outside your network, use the ping and port checker.
Ping sends ICMP packets to a host and measures response time. Port scanning checks which TCP ports are open and accepting connections — helping diagnose serviceavailability issues.
Choose packet count (3, 4, 6, 10). Stats: min/avg/max latency and packet loss.
Check 14 key ports: HTTP, HTTPS, SSH, FTP, SMTP, MySQL, PostgreSQL, and more.
Testing from our server — see site availability from outside, not just your local network.
Need constant monitoring? Create a monitor — checks every minute with notifications.
availability diagnosis
TCP port scanning
connection debugging
basic health check
Ping check history, host availability monitoring and downtime alerts.
Sign up freeBoth carry the code ECONNRESET. socket hang up is the message the Node.js http client uses when the connection closes before a response arrives.
Usually a keep-alive race: the client reuses an idle socket at the moment the server closes it. Make the server's keep-alive timeout longer than the client's.
Retry once for idempotent requests such as GET, ideally only when the socket was reused. Do not blindly retry non-idempotent POSTs.
It is reported by the side that received the reset. The cause is on the other side or in between: a closed keep-alive socket, a crash, a proxy timeout or a firewall.
104 is the Linux number for ECONNRESET; Node.js reports system errors as negative errno values.
Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.