This error occurs when Node.js attempts to establish a TCP connection to a server (database, API, or service) but the connection is actively refused. The target server is either not running, not listening on the specified port, or actively rejecting connections due to firewall rules or network configuration.
ECONNREFUSED is a Node.js error code indicating that a connection attempt was actively refused by the target machine. This happens when your application tries to connect to a server on a specific host and port, but nothing is listening on that address or the connection is blocked. The error is part of Node.js's network error codes and represents a TCP-level connection failure. Unlike timeout errors (ETIMEDOUT), ECONNREFUSED means the target machine responded and explicitly rejected the connection. This is typically because no process is bound to the port you're trying to reach. This error commonly occurs with database connections (PostgreSQL on port 5432, MongoDB on port 27017, Redis on port 6379), HTTP API calls, or inter-service communication in microservice architectures. The 127.0.0.1 address indicates localhost, meaning your application is trying to connect to a service on the same machine.
Check if the service you're trying to connect to is actually running:
For PostgreSQL:
# Linux/macOS
sudo systemctl status postgresql
# or
ps aux | grep postgres
# Check if PostgreSQL is listening on port 5432
sudo lsof -i :5432
# or
netstat -an | grep 5432For MongoDB:
sudo systemctl status mongod
sudo lsof -i :27017For custom Node.js services:
# Check if anything is listening on the port
lsof -i :3000
netstat -an | grep LISTEN | grep 3000If nothing is listening on the port, start the required service before running your application.
Double-check that your application is using the correct host and port:
// PostgreSQL connection example
const { Client } = require('pg');
const client = new Client({
host: '127.0.0.1', // Verify this matches where service is running
port: 5432, // Verify correct port
database: 'mydb',
user: 'postgres',
password: 'password'
});
client.connect()
.then(() => console.log('Connected successfully'))
.catch(err => {
console.error('Connection error:', err.code, err.message);
console.error('Attempted connection to:', client.host + ':' + client.port);
});Common mistakes:
- Using port 5432 when PostgreSQL is on 5433
- Forgetting to specify protocol (http:// vs https://)
- Mixing up localhost, 127.0.0.1, and 0.0.0.0
Node.js 17+ prefers IPv6, which can cause connection issues. Explicitly use IPv4:
// Before (may fail on Node.js 17+)
const client = new Client({
host: 'localhost',
port: 5432
});
// After (works reliably)
const client = new Client({
host: '127.0.0.1',
port: 5432
});Or configure your service to listen on both IPv4 and IPv6:
For PostgreSQL in postgresql.conf:
listen_addresses = '*'For custom Node.js servers:
// Listen on all interfaces
app.listen(3000, '0.0.0.0', () => {
console.log('Server listening on all interfaces port 3000');
});Add retry logic to handle services that take time to start up:
async function connectWithRetry(maxRetries = 5, delay = 2000) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
await client.connect();
console.log('Connected successfully');
return;
} catch (err) {
if (err.code === 'ECONNREFUSED') {
console.log(`Connection attempt ${attempt}/${maxRetries} failed`);
if (attempt === maxRetries) {
throw new Error('Max retries reached. Service may not be running.');
}
console.log(`Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
// Different error, don't retry
throw err;
}
}
}
}
connectWithRetry()
.catch(err => {
console.error('Failed to connect:', err.message);
process.exit(1);
});This is especially useful in Docker environments where services start in parallel.
Ensure firewall rules aren't blocking the connection:
Linux (UFW):
# Check firewall status
sudo ufw status
# Allow PostgreSQL port
sudo ufw allow 5432/tcp
# For local development, you can temporarily disable
sudo ufw disablemacOS:
# Check if firewall is blocking the port
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstateWindows:
# Check if port is blocked
Test-NetConnection -ComputerName 127.0.0.1 -Port 5432For Docker containers trying to reach host services:
# docker-compose.yml
services:
app:
network_mode: "host" # Access host services directly
# Or use host.docker.internal on Docker DesktopWhen running Node.js in Docker and connecting to host services:
Option 1 - Use host.docker.internal (Docker Desktop):
const client = new Client({
host: 'host.docker.internal', // Docker Desktop
port: 5432
});Option 2 - Use host network mode:
# docker-compose.yml
services:
app:
network_mode: "host"Option 3 - Run database in Docker too:
services:
app:
depends_on:
- postgres
environment:
DATABASE_HOST: postgres # Use service name
postgres:
image: postgres:15
ports:
- "5432:5432"Option 4 - On Linux, use host gateway:
docker run --add-host=host.docker.internal:host-gateway your-imageDebugging Connection Issues Systematically
Use telnet or nc (netcat) to test if the port is reachable:
# Test if port is accessible
telnet 127.0.0.1 5432
# or
nc -zv 127.0.0.1 5432If this fails, the issue is at the service level, not your Node.js code.
PostgreSQL Specific Considerations
PostgreSQL's pg_hba.conf controls connection permissions. Ensure localhost connections are allowed:
# pg_hba.conf
host all all 127.0.0.1/32 md5
host all all ::1/128 md5After changing, reload PostgreSQL:
sudo systemctl reload postgresqlMongoDB IPv6 Issues
MongoDB may bind only to IPv6 on some systems. Check mongod.conf:
net:
bindIp: 127.0.0.1,::1 # Both IPv4 and IPv6
port: 27017Environment-Specific Connection Strings
Use environment variables to handle different environments:
const client = new Client({
host: process.env.DB_HOST || '127.0.0.1',
port: parseInt(process.env.DB_PORT || '5432'),
database: process.env.DB_NAME || 'mydb'
});.env for development:
DB_HOST=127.0.0.1
DB_PORT=5432.env.docker for Docker:
DB_HOST=postgres
DB_PORT=5432Health Checks in Production
Implement health check endpoints that verify database connectivity:
app.get('/health', async (req, res) => {
try {
await client.query('SELECT 1');
res.status(200).json({ status: 'healthy', database: 'connected' });
} catch (err) {
if (err.code === 'ECONNREFUSED') {
res.status(503).json({
status: 'unhealthy',
database: 'connection_refused',
error: 'Database service not reachable'
});
} else {
res.status(503).json({ status: 'unhealthy', error: err.message });
}
}
});CI/CD Pipeline Considerations
In GitHub Actions or similar CI environments, ensure services are ready before tests:
services:
postgres:
image: postgres:15
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432Port Conflicts
If you get ECONNREFUSED because the port is taken, find what's using it:
# Linux/macOS
sudo lsof -i :5432
# Kill the process if needed
sudo kill -9 <PID>
# Windows
netstat -ano | findstr :5432
taskkill /PID <PID> /FError: 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