How to Fix The Debug Error ECONNRESET in Node.js?

Hi! I’m a developer who once spent hours (okay, days) scratching my head over a mysterious and frustrating error in my Node.js chat app. The app used Express.js and Socket.io, and everything looked great until it didn’t.

Let me walk you through how I handled the dreaded:

Error: read ECONNRESET

Define the Problem?

I had built a real time chat app using Express.js and Socket.io. Pretty standard setup: users could join rooms, chat, and everything ran through a proxy (HAProxy). I had wrapped the Node.js server with forever to automatically restart it on crash.

But here’s the catch: randomly, about 5 times a day, the app would crash with a read ECONNRESET error. That restart would kick users out of their chat rooms. Not cool.

The First Code Example (Flash Socket Server)

One of the parts of my project was serving a Flash socket policy file.

Here’s the original code:

net = require("net");

net.createServer((socket) => {
socket.write('<?xml version="1.0"?>\n');
socket.write('<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">\n');
socket.write('<cross-domain-policy>\n');
socket.write('<allow-access-from domain="*" to-ports="*"/>\n');
socket.write('</cross-domain-policy>\n');
socket.end();
}).listen(843);

It worked, but I started to wonder was this contributing to the ECONNRESET crashes?

What Is the Error ECONNRESET?

ECONNRESET means “Connection Reset by Peer.”

Basically, my Node.js app was trying to talk to another service (HTTP, Redis, MySQL, or even a browser tab), but the other side suddenly closed the connection. This can happen for a bunch of reasons:

  • The client left or refreshed the page
  • HAProxy decided the connection was idle and dropped it
  • A database or API connection timed out
  • A bug in a third-party service

Define a More Error Handling

Here’s why this error caused so many headaches:

  • If not handled, the error crashes the Node.js process
  • My forever script restarted the app… every single time
  • Users were disconnected from chat rooms mid-conversation
  • The stack trace only pointed to internal Node modules (net.js) no clue where it happened in my code

How I Fix It

Added Global Error Handling

At first, I slapped on this global handler:

process.on('uncaughtException', function (err) {
console.error("Caught exception:", err.stack || err);
console.log("Node NOT Exiting...");
});

It worked the server stayed up, and users weren’t booted. But this was just a band-aid. I needed better solutions.

Wrapped All My Event Emitters with Error

For WebSocket connections:

io.on('connection', (socket) => {
socket.on('error', (err) => {
console.error('Socket error:', err);
});
});

For HTTP requests:

const http = require('http');

const req = http.get('http://example.com', (res) => {
// handle response
});

req.on('error', (err) => {
console.error('HTTP Request Error:', err.message);
});

Lesson learned: Always .on('error') anything that can emit one.

Installed longjohn for Better Stack Traces

This was a life-saver for tracing async call stacks:

npm install longjohn

Then in my main file:

require('longjohn');

Now the stack traces showed me exactly which part of my code triggered the issue not just a vague net.js reference.

Error Listeners for MySQL

I made sure to handle errors on my DB connections too:

For MySQL:

connection.on('error', function(err) {
console.error('MySQL error:', err);
});

For Redis:

client.on('error', function (err) {
console.log('Redis error:', err);
});

Sometimes the error was coming from lost DB connections, not the sockets.

A Better Chat App Example

To prevent these crashes and keep users online, I updated my app like this:

 express = require('express');
const http = require('http');
const socketIo = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

app.get('/', async (req, res) => {
try {
// Simulate DB call
await new Promise((resolve) => setTimeout(resolve, 100));
res.send('Hello, world!');
} catch (err) {
res.status(500).send('Something went wrong!');
}
});

io.on('connection', (socket) => {
console.log('New user connected');

socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});

socket.on('error', (err) => {
console.error('WebSocket error:', err);
});

socket.on('disconnect', () => {
console.log('User disconnected');
});
});

server.listen(3000, () => {
console.log('Listening on *:3000');
});

Tips to Prevent ECONNRESET

Here are my go-to rules now:

  • Use keep-alive connections in HTTP to avoid drops
  • Handle every .on('error') possibility
  • Configure HAProxy with sensible timeouts
  • Monitor Redis/MySQL for connection limits or drops
process.on('unhandledRejection', (reason) => {
console.error('Unhandled Rejection:', reason);
});

Final Thought

Here’s the deal: ECONNRESET isn’t always your fault but not handling it is. Once I started treating every connection as a potential failure point, my app became more stable. I stopped relying on forever restarts and started catching exceptions the right way.

Related blog posts