How to fix Error: read ECONNRESET in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025· 364 views

This error occurs when a TCP connection is forcibly closed by the remote server or network device before your Node.js application finishes reading data. The connection is abruptly terminated by sending a TCP RST packet instead of a graceful close.

Quick fix

Fixes ECONNRESET

const https = require('https');

async function makeRequest(url) {
  try {
    const response = await fetch(url);
    return await response.json();
  } catch (error) {
    if (error.code === 'ECONNRESET') {
      console.error('Connection reset by server:', error.message);
      // Implement retry logic here
    }
    throw error;
  }
}
  1. Add proper error handling to catch connection resets
  2. Configure HTTP keep-alive settings properly
  3. Implement retry logic with exponential backoff
  4. Use connection pooling with proper limits
node.js — error
const https = require('https');
async function makeRequest(url) {
try {
const response = await fetch(url);
return await response.json();
} catch (error) {
if (error.code === 'ECONNRESET') {
console.error('Connection reset by server:', error.message);
// Implement retry logic here
}
throw error;
}
}
Error: read ECONNRESET

What this error means

The ECONNRESET error is a network-level error that occurs at the TCP layer when one side of a connection sends a TCP RST (reset) packet, indicating an immediate closure of the connection. In Node.js, this typically happens during HTTP requests, database connections, or any network operation when the remote server or an intermediate network device terminates the connection unexpectedly. This error is particularly common with HTTP keep-alive connections, where persistent connections are reused for multiple requests. When the server closes an idle connection due to timeout while the client attempts to send a request on that socket, you'll see ECONNRESET. The "peer" in "connection reset by peer" refers to the remote end of the connection - the server, service, or network device that initiated the connection closure. Unlike a graceful connection close (FIN packet), a reset is an abrupt termination that doesn't allow the other side to finish sending or receiving data.

Typical symptoms

  • HTTP requests fail intermittently with "Error: read ECONNRESET"
  • Database queries fail with connection reset errors
  • Error occurs more frequently during periods of low request volume
  • Requests succeed when retried immediately after failure
  • Issues appear when using HTTP keep-alive or connection pooling
  • External API calls fail unexpectedly in production but work in development

Common causes

  1. Server closes idle keep-alive connections due to timeout mismatch between client and server
  2. Load balancer or proxy terminates connections after inactivity period
  3. Server is overwhelmed and forcibly closes connections to shed load
  4. Firewall or security software blocks or terminates the connection
  5. Network instability or packet loss between client and server
  6. Server crashes or restarts while handling requests
  7. Large request/response payloads exceed server limits
  8. SSL/TLS handshake failures or certificate issues
  9. Incorrect HTTP protocol usage (missing req.end() in client code)
  10. Server-side timeout configured shorter than expected request duration

How to fix "Error: read ECONNRESET"

1Add proper error handling to catch connection resets

Wrap your network operations in try-catch blocks to gracefully handle ECONNRESET errors:

javascript
const https = require('https');

async function makeRequest(url) {
  try {
    const response = await fetch(url);
    return await response.json();
  } catch (error) {
    if (error.code === 'ECONNRESET') {
      console.error('Connection reset by server:', error.message);
      // Implement retry logic here
    }
    throw error;
  }
}

For http.request, listen for the 'error' event:

javascript
const req = https.request(options, (res) => {
  // Handle response
});

req.on('error', (error) => {
  if (error.code === 'ECONNRESET') {
    console.error('Connection was reset');
  }
});

req.end();
2Configure HTTP keep-alive settings properly

Adjust keep-alive timeouts to ensure client closes connections before the server does. The client timeout should be shorter than the server timeout:

javascript
const http = require('http');

// For Node.js server
const server = http.createServer((req, res) => {
  res.end('Hello');
});

// Set keep-alive timeout (default is 5 seconds)
server.keepAliveTimeout = 61000; // 61 seconds
server.headersTimeout = 62000;   // 62 seconds (should be > keepAliveTimeout)

server.listen(3000);

For HTTP clients using the default agent:

javascript
const http = require('http');

const agent = new http.Agent({
  keepAlive: true,
  keepAliveMsecs: 30000,  // Send keep-alive probes every 30s
  maxSockets: 50,
  maxFreeSockets: 10,
  timeout: 60000,
  scheduling: 'lifo'  // Use most recent socket first (reduces stale connections)
});

const options = {
  hostname: 'api.example.com',
  port: 443,
  path: '/data',
  method: 'GET',
  agent: agent
};
3Implement retry logic with exponential backoff

Add automatic retry for transient connection errors:

javascript
async function fetchWithRetry(url, options = {}, maxRetries = 3) {
  let lastError;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      return response;
    } catch (error) {
      lastError = error;

      // Retry on ECONNRESET and other network errors
      if (error.code === 'ECONNRESET' ||
          error.code === 'ETIMEDOUT' ||
          error.code === 'ENOTFOUND') {

        if (attempt < maxRetries) {
          // Exponential backoff: 1s, 2s, 4s
          const delay = Math.pow(2, attempt) * 1000;
          console.log(`Retry attempt ${attempt + 1} after ${delay}ms`);
          await new Promise(resolve => setTimeout(resolve, delay));
          continue;
        }
      }

      throw error;
    }
  }

  throw lastError;
}

// Usage
const data = await fetchWithRetry('https://api.example.com/data');

For axios:

javascript
const axios = require('axios');

const axiosInstance = axios.create({
  timeout: 30000,
  httpsAgent: new https.Agent({ keepAlive: true })
});

// Add retry interceptor
axiosInstance.interceptors.response.use(null, async (error) => {
  const config = error.config;

  if (!config || !config.retry) {
    config.retry = 0;
  }

  if (config.retry >= 3) {
    return Promise.reject(error);
  }

  if (error.code === 'ECONNRESET') {
    config.retry += 1;
    const delay = Math.pow(2, config.retry) * 1000;
    await new Promise(resolve => setTimeout(resolve, delay));
    return axiosInstance(config);
  }

  return Promise.reject(error);
});
4Use connection pooling with proper limits

Configure connection pools to prevent socket exhaustion and stale connections:

javascript
const https = require('https');

const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 50,           // Max concurrent sockets
  maxFreeSockets: 10,       // Max idle sockets to keep
  timeout: 60000,           // Socket timeout
  freeSocketTimeout: 30000, // Close idle sockets after 30s
  scheduling: 'lifo'        // Use most recent sockets first
});

// Use the agent for all requests
const options = {
  hostname: 'api.example.com',
  agent: agent
};

For database connections (using a connection pool library):

javascript
const { Pool } = require('pg');

const pool = new Pool({
  host: 'localhost',
  port: 5432,
  database: 'mydb',
  max: 20,                    // Max pool size
  idleTimeoutMillis: 30000,   // Close idle connections after 30s
  connectionTimeoutMillis: 2000,
  keepAlive: true,
  keepAliveInitialDelayMillis: 10000
});

// Handle pool errors
pool.on('error', (err, client) => {
  console.error('Unexpected error on idle client', err);
});
5Check network and infrastructure issues

Investigate infrastructure problems that might cause connection resets:

1. Check load balancer timeout settings: Ensure load balancer idle timeout is greater than your application's keep-alive timeout.

2. Review firewall rules: Some firewalls aggressively close idle connections. Check iptables or cloud security groups.

3. Monitor server resource usage: High CPU or memory usage can cause servers to drop connections:

bash
# Check server resources
top
free -m
netstat -an | grep ESTABLISHED | wc -l

4. Test network stability:

bash
# Test connection to the problematic endpoint
ping api.example.com
traceroute api.example.com

# Check for packet loss
mtr api.example.com

5. Review server logs: Check nginx/apache logs for connection closures:

bash
# Nginx error log
tail -f /var/log/nginx/error.log | grep "connection"

# Check for timeout configurations
grep -r "keepalive_timeout" /etc/nginx/
6Adjust timeout configurations

Increase timeout values if legitimate requests are timing out:

javascript
// For fetch API (Node.js 18+)
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 60000); // 60s timeout

try {
  const response = await fetch('https://api.example.com/data', {
    signal: controller.signal
  });
  clearTimeout(timeoutId);
} catch (error) {
  if (error.name === 'AbortError') {
    console.error('Request timed out');
  }
}

For axios:

javascript
const axios = require('axios');

const instance = axios.create({
  timeout: 60000, // 60 seconds
  httpAgent: new http.Agent({
    keepAlive: true,
    timeout: 60000
  }),
  httpsAgent: new https.Agent({
    keepAlive: true,
    timeout: 60000
  })
});

For socket connections:

javascript
const net = require('net');

const socket = net.connect({
  host: 'example.com',
  port: 80
});

socket.setTimeout(60000); // 60 second timeout

socket.on('timeout', () => {
  console.log('Socket timeout');
  socket.destroy();
});

Advanced notes

Understanding Keep-Alive Race Conditions

A common cause of ECONNRESET is the keep-alive race condition: when a client attempts to reuse a socket at the exact moment the server decides to close it due to timeout. This is particularly problematic when client and server timeouts are similar.

Best practice: Set client-side timeouts 5-10 seconds shorter than server timeouts. For example, if your server keep-alive is 60 seconds, set client to 50-55 seconds.

LIFO vs FIFO Socket Scheduling

The 'scheduling' option in http.Agent determines which socket is selected from the pool:
- FIFO (first-in-first-out): Round-robin usage, but increases risk of picking stale sockets
- LIFO (last-in-first-out): Uses most recently active sockets, reducing stale socket issues

For low-traffic applications, LIFO significantly reduces ECONNRESET errors.

Dealing with Cloud Load Balancers

AWS ALB has a 60-second idle timeout by default. GCP Load Balancer defaults to 30 seconds. Azure defaults to 4 minutes. Always ensure your application's keep-alive timeout is shorter than your load balancer's timeout.

Production Monitoring

Set up monitoring for ECONNRESET errors to detect patterns:

javascript
const errorCounts = new Map();

process.on('uncaughtException', (error) => {
  if (error.code === 'ECONNRESET') {
    const count = errorCounts.get('ECONNRESET') || 0;
    errorCounts.set('ECONNRESET', count + 1);

    // Alert if error rate exceeds threshold
    if (count > 100) {
      // Send alert to monitoring service
    }
  }
});

SSL/TLS Considerations

ECONNRESET can occur during TLS handshake failures. Enable TLS debugging:

bash
NODE_DEBUG=tls node app.js

Check certificate validity and ensure proper CA bundle configuration for self-signed certificates.

Frequently asked questions

What does "ECONNRESET" mean?
The ECONNRESET error is a network-level error that occurs at the TCP layer when one side of a connection sends a TCP RST (reset) packet, indicating an immediate closure of the connection. js, this typically happens during HTTP requests, database connections, or any network operation when the remote server or an intermediate network device terminates the connection unexpectedly. This error is particularly common with HTTP keep-alive connections, where persistent connections are reused for multiple requests.
How do I fix "ECONNRESET"?
This error occurs when a TCP connection is forcibly closed by the remote server or network device before your Node.js application finishes reading data. The connection is abruptly terminated by sending a TCP RST packet instead of a graceful close.
What causes "ECONNRESET"?
Server closes idle keep-alive connections due to timeout mismatch between client and server Load balancer or proxy terminates connections after inactivity period Server is overwhelmed and forcibly closes connections to shed load
Is the "ECONNRESET" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading