This error occurs when a Node.js application attempts to connect to a TCP port but the connection is actively refused because no service is listening on that port. It commonly happens with database connections, API calls to localhost, or inter-service communication when the target server is not running or the port configuration is incorrect.
ECONNREFUSED is a Node.js error code indicating that a TCP connection attempt was actively rejected by the target machine. When your application tries to establish a connection using modules like http, net, or database clients, it sends a TCP SYN packet to the specified host and port. If no process is listening on that port, the operating system responds with a TCP RST (reset) packet, which Node.js translates into this error. This is not a network timeout or DNS resolution failure - it's an explicit refusal from the target system. The error means the network path to the host is working, but nothing is accepting connections on the specified port. This commonly occurs during development when a database server, API server, or microservice hasn't been started yet, or in production when services crash or restart. The error typically includes the IP address and port in the format "ECONNREFUSED 127.0.0.1:5000", making it clear which connection failed. Understanding the distinction between ECONNREFUSED and other connection errors like ETIMEDOUT or ENOTFOUND is crucial for effective troubleshooting.
Check if the server or database you're trying to connect to is actually running. For a Node.js server:
# Check if any process is listening on the port
lsof -i :5000
# or on Linux
netstat -tuln | grep :5000
# or use ss command
ss -tuln | grep :5000If no process is listed, the server is not running. Start your server in a separate terminal:
# For a Node.js application
node server.js
# For a development server
npm run dev
# For a database like PostgreSQL
sudo systemctl start postgresqlEnsure the server logs show it's listening on the expected port before attempting connections.
Verify that your client code is using the correct port number that the server is actually listening on:
// Check your connection configuration
const PORT = process.env.PORT || 5000; // Make sure this matches
// For HTTP requests
const response = await fetch(`http://localhost:${PORT}/api`);
// For database connections
const client = new Client({
host: 'localhost',
port: 5432, // Ensure this matches your database server
database: 'mydb'
});Common mismatches:
- Database clients using default ports (5432 for PostgreSQL, 3306 for MySQL) when server uses custom ports
- Environment variables not loaded correctly
- Different ports in development vs production configurations
Ensure the server is listening on the correct network interface. A server bound only to 127.0.0.1 won't accept connections from other interfaces:
// Server binding to all interfaces (accessible from anywhere)
app.listen(PORT, '0.0.0.0', () => {
console.log(`Server running on all interfaces port ${PORT}`);
});
// Server binding only to localhost (only local connections)
app.listen(PORT, '127.0.0.1', () => {
console.log(`Server running on localhost:${PORT}`);
});For Docker containers, use 0.0.0.0 to allow connections from the host:
// In containerized environments
const HOST = '0.0.0.0';
const PORT = 5000;
app.listen(PORT, HOST);When connecting from outside the container, use localhost or 127.0.0.1 on the host machine if ports are properly mapped.
Implement retry logic to handle cases where the server takes time to start:
async function connectWithRetry(url, maxRetries = 5, delay = 1000) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
console.log('Connected successfully');
return response;
} catch (err) {
if (err.code === 'ECONNREFUSED') {
console.log(`Connection refused, retry ${i + 1}/${maxRetries}`);
if (i < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, delay));
delay *= 2; // Exponential backoff
} else {
throw new Error('Max retries reached, server not available');
}
} else {
throw err; // Different error, don't retry
}
}
}
}
// Usage
try {
await connectWithRetry('http://localhost:5000/health');
} catch (err) {
console.error('Failed to connect:', err.message);
}This is especially useful in Docker Compose setups where services start in parallel.
Check if firewall rules or security software is blocking the connection:
# Temporarily test with firewall disabled (Linux)
sudo ufw status
sudo ufw allow 5000/tcp
# Windows - check Windows Defender Firewall
# Add inbound rule for your port in Windows Defender settings
# macOS - check if Little Snitch or similar software is blockingFor local development, the firewall typically isn't an issue for localhost connections, but corporate security software or VPNs can interfere.
Also check for proxy settings that might redirect localhost connections:
// Bypass proxy for localhost in Node.js
process.env.NO_PROXY = 'localhost,127.0.0.1';Add proper error handling to provide clear feedback when connections fail:
const http = require('http');
const options = {
hostname: 'localhost',
port: 5000,
path: '/api',
method: 'GET'
};
const req = http.request(options, (res) => {
console.log(`Status: ${res.statusCode}`);
res.on('data', (data) => console.log(data.toString()));
});
req.on('error', (err) => {
if (err.code === 'ECONNREFUSED') {
console.error('Cannot connect to server on port 5000');
console.error('Please ensure the server is running');
console.error('Start it with: npm run server');
} else {
console.error('Connection error:', err);
}
});
req.end();This makes it immediately clear to developers what action they need to take.
Docker Networking and Host Connections
When running Node.js in Docker and connecting to services on the host machine, use the special DNS name host.docker.internal instead of localhost:
// Inside Docker container connecting to host
const dbConfig = {
host: 'host.docker.internal', // Not 'localhost' or '127.0.0.1'
port: 5432
};On Linux, you may need to use the host's network IP or add --add-host=host.docker.internal:host-gateway to your docker run command.
Testing Port Availability Programmatically
Before attempting connections, test if a port is available:
const net = require('net');
function isPortOpen(port, host = 'localhost', timeout = 2000) {
return new Promise((resolve) => {
const socket = new net.Socket();
socket.setTimeout(timeout);
socket.once('error', () => resolve(false));
socket.once('timeout', () => {
socket.destroy();
resolve(false);
});
socket.connect(port, host, () => {
socket.end();
resolve(true);
});
});
}
// Usage
if (await isPortOpen(5000)) {
console.log('Server is ready');
} else {
console.log('Server is not available');
}Health Check Endpoints
Implement health check endpoints in your services to verify they're ready:
// Server-side health check
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok', timestamp: Date.now() });
});
// Client-side health check before connecting
async function waitForServer(url, timeout = 30000) {
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
try {
const response = await fetch(`${url}/health`);
if (response.ok) return true;
} catch (err) {
// Server not ready yet
}
await new Promise(resolve => setTimeout(resolve, 500));
}
throw new Error('Server health check timeout');
}Common Port Conflicts
Be aware of commonly used ports that may conflict:
- 3000: Create React App, many Node.js dev servers
- 5000: Flask (Python), many tutorial examples
- 8000: Django, Python SimpleHTTPServer
- 8080: Alternative HTTP port, Tomcat, many proxies
Use lsof -i :[PORT] or netstat to identify what's using a port.
IPv4 vs IPv6 Issues
Some systems resolve localhost to IPv6 (::1) while servers bind to IPv4 (127.0.0.1):
// Explicitly use IPv4
const client = new Client({
host: '127.0.0.1', // Not 'localhost'
port: 5432
});
// Or configure server to listen on both
server.listen(PORT, '::', () => {
console.log('Listening on IPv4 and IPv6');
});Error: EMFILE: too many open files, watch
EMFILE: fs.watch() limit exceeded
Error: Middleware next() called multiple times (next() invoked twice)
Express middleware next() called multiple times
Error: Worker failed to initialize (worker startup error)
Worker failed to initialize in Node.js
Error: EMFILE: too many open files, open 'file.txt'
EMFILE: too many open files
Error: cluster.fork() failed (cannot create child process)
cluster.fork() failed - Cannot create child process