Node.js ECONNRESET Error: Causes and Production Fixes
'read ECONNRESET' or 'fetch failed' in Node.js? The peer closed the socket. Learn the keep-alive mismatch behind most cases and how to fix it with retries and timeouts.
ECONNRESET in Node.js means the other side of a TCP connection closed it abruptly while you were using it; in production it is most often a keep-alive timeout mismatch between your client and a server or load balancer, and it is fixed by aligning timeouts and retrying idempotent requests.
You will see it in several forms:
Error: read ECONNRESET
Error: socket hang up
TypeError: fetch failed cause: Error: read ECONNRESET
Why It Happens
| Cause | Typical situation |
|---|---|
| Reused idle socket closed by server | HTTP keep-alive: server drops idle connection, client reuses it just as it dies |
| Load balancer idle timeout shorter than your server's | Requests fail after a quiet period |
| Upstream crashed or restarted | Deploys, OOM kills, autoscaling |
| Proxy or firewall dropped a long request | Long calls through NAT or a corporate proxy |
| Client aborted | User closed the tab, your code timed out |
The first two explain most intermittent errors: they look random, appear after traffic lulls, and vanish on retry.
Fix 1: Make Your Server Outlive the Load Balancer
If your Node server closes idle keep-alive connections before the load balancer does, the balancer forwards a request on a connection that is already dead, and the client gets a reset or a 502. Node's default keepAliveTimeout is 5 seconds, which is shorter than many balancers' idle timeouts.
const server = app.listen(3000)
server.keepAliveTimeout = 65_000 // longer than the LB idle timeout (for example 60s)
server.headersTimeout = 66_000 // must be greater than keepAliveTimeout
Check your load balancer's idle timeout value and set yours above it. A resulting 502 at the proxy layer is covered in nginx 502 Bad Gateway fixes.
Fix 2: Retry Safe Requests With Backoff
Retry only idempotent requests (GET, PUT, DELETE, or POSTs with an idempotency key), with a small cap and jitter:
async function fetchWithRetry(url: string, init: RequestInit = {}, tries = 3) {
for (let i = 0; i < tries; i++) {
try {
return await fetch(url, { ...init, signal: AbortSignal.timeout(8000) })
} catch (e: any) {
const code = e?.cause?.code ?? e?.code
const retryable = ['ECONNRESET', 'ETIMEDOUT', 'UND_ERR_SOCKET'].includes(code)
if (!retryable || i === tries - 1) throw e
await new Promise(r => setTimeout(r, 200 * 2 ** i + Math.random() * 100))
}
}
}
Never blindly retry a payment or an email send. The full pattern, including budgets and circuit breakers, is in API Timeout Errors in Node.js.
Fix 3: Handle the Error Event or Crash
An unhandled error event on a socket or stream crashes the process. Attach handlers, and make sure rejections are caught; see unhandled promise rejections and Node.js production error handling.
req.on('error', err => logger.warn({ err }, 'upstream reset'))
Fix 4: Check Whether Your Own Server Is Dying
If many clients report resets at the same moment, your process may be restarting. Look for out-of-memory kills (see Docker exit code 137), crashes after deploy, or a blocked event loop that stops accepting connections (event loop blocked).
Diagnose in 3 Steps
- Log
err.code, the target host, and elapsed time on each failure. - Check whether errors cluster after idle periods (keep-alive) or at deploy time (restarts).
- Compare your server's
keepAliveTimeoutwith every proxy and load balancer in front of it.
Let Relia Separate Noise From Outages
A single ECONNRESET is routine; a burst is an incident. Relia learns what is normal for your app and only tells you when it matters: it writes the incident up in plain words: what happened, why it thinks so (with a confidence level), and one thing to do next. On request it writes a fix plan, such as aligning timeouts or adding retry logic, with a "Copy for your AI assistant" button; Relia doesn't change code itself.
FAQ
What does read ECONNRESET mean?
The remote end reset the TCP connection while your code was reading from it.
Is ECONNRESET my bug or the server's?
Either. Keep-alive mismatches are configuration bugs on one side; bursts usually mean the remote service is restarting or overloaded.
Should I retry on ECONNRESET?
Yes for idempotent requests, with backoff and a limit. Not for non-idempotent writes without an idempotency key.