Fixing 'Error: socket hang up' in Node.js HTTPS Requests

intermediate💚 Node.js2026-04-11| Node.js (v12+), Axios, node-fetch, or native https module on Linux/macOS/Windows

Error Message

Error: socket hang up
#nodejs#https#axios#debugging#networking

What exactly is a 'Socket Hang Up'?Few things are as frustrating as the Error: socket hang up. It is the networking equivalent of someone hanging up the phone mid-sentence. Your Node.js application successfully established a connection, but the server or a middleman—like a load balancer—terminated it before the response finished.

Technically, this usually manifests as an ECONNRESET. While a ETIMEDOUT means you couldn't even reach the server, a hang up means you were talking, but the line went dead. This often happens because of mismatched timeout settings or exhausted connection pools.

Error: socket hang up
    at connResetException (internal/errors.js:607:14)
    at TLSSocket.socketOnEnd (_http_client.js:493:23)
    at TLSSocket.emit (events.js:327:22)
    at endReadableNT (internal/streams/readable.js:1327:12)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) {
  code: 'ECONNRESET'
}

Finding the CulpritBefore you start rewriting code, you need to pinpoint where the connection is breaking. Is it your code, the network, or the remote server?

  • Check Server-Side Logs: Did the API server crash? Look for memory spikes or 500-series errors at the exact timestamp of the hang up.- Audit the Network Path: If you are behind a corporate VPN or using an AWS Application Load Balancer (ALB), these intermediaries often have a 60-second idle timeout. If your request takes 61 seconds, the ALB will kill the socket.- Run a Verbose Trace: Execute curl -v https://api.example.com. This helps you see if the server expects specific headers, like a User-Agent, that your Node script might be skipping.- Enable Node.js Debugging: Launch your app using NODE_DEBUG=http,https,net node app.js. You will see the low-level handshake and exactly when the FIN packet is received.## Proven Solutions### 1. Use a Persistent HTTP AgentNode.js versions prior to v19 do not enable Keep-Alive by default. This means every request opens and closes a new TCP connection, which is slow and prone to failure. Reusing connections via a persistent agent is the single most effective fix for this error. For the native https module:
const https = require('https');

const agent = new https.Agent({
  keepAlive: true,
  keepAliveMsecs: 1000, // Sends TCP keep-alive probes every 1s
  timeout: 60000        // Matches standard 60s server idle timeouts
});

const options = {
  hostname: 'api.example.com',
  path: '/large-dataset',
  agent: agent 
};

const req = https.request(options, (res) => { /* handle res */ });
req.on('error', (e) => console.error(e));
req.end();

For Axios users:

const axios = require('axios');
const https = require('https');

const instance = axios.create({
  // Keep-Alive reduces handshake overhead and prevents abrupt closures
  httpsAgent: new https.Agent({ keepAlive: true }),
});

instance.get('https://api.example.com/data')
  .then(res => console.log(res.data))
  .catch(err => console.error(err.message));

2. Align Your TimeoutsIf your server takes 30 seconds to process a heavy database query but your Node.js socket defaults to a shorter window, the client will drop the connection. You must ensure your local timeout is slightly longer than the server's maximum processing time.

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

// Increase socket timeout to 2 minutes for slow reports
req.setTimeout(120000, () => {
  console.warn('Socket idle for 120s. Manually aborting.');
  req.destroy();
});

3. Calculate Content-Length for POST RequestsMany modern firewalls and Nginx configurations will instantly drop a POST request if the Content-Length header is missing or incorrect. This is a security measure to prevent request smuggling. Don't rely on Node to guess the size; calculate it explicitly.

const data = JSON.stringify({ user: 'jsmith', action: 'sync' });
const options = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(data),
    'User-Agent': 'MyApp/1.0.0'
  }
};

How to Verify the FixOnce you've implemented a persistent agent or adjusted timeouts, put the connection through its paces:

  • The Loop Test: Run 50 consecutive requests. If the issue was socket exhaustion, the first 10 might have worked before, but now all 50 should pass.- Monitor Active Handles: Use process._getActiveHandles() in your dev environment. It helps you confirm that sockets are being reused and not leaking into an 'infinite' open state.- Check Proxy Logs: If you use Nginx, look for upstream prematurely closed connection. If that error disappears from Nginx logs, your Node.js Agent configuration is working correctly.## The Bottom Line- Keep-Alive is non-negotiable: For high-traffic apps, always use an Agent to manage connection persistence.- Handle Errors Gracefully: Always attach an .on('error') listener. Without it, a simple socket hang up can trigger an uncaughtException and crash your entire process.- Watch the Middlemen: Your code might be perfect, but an AWS Load Balancer or Cloudflare worker with a short timeout will still hang up on you if your backend is slow.

Related Error Notes