error nodejs

Node.js ECONNREFUSED

Understanding Node.js ECONNREFUSED error - the connection attempt was refused because the target server is not accepting connections.

What It Means

ECONNREFUSED is a system-level error that occurs when Node.js attempts to connect to a server, but the connection is actively refused. This means the target host is reachable, but nothing is listening on the specified port. The full error typically reads: connect ECONNREFUSED 127.0.0.1:3000.

Common Causes

  • The target server or service is not running
  • Wrong port number in the connection configuration
  • Wrong hostname or IP address
  • Service hasn’t finished starting yet (race condition)
  • Database server is not running (PostgreSQL, MySQL, Redis, MongoDB)
  • Firewall blocking the connection
  • Docker container networking misconfiguration

How to Fix

Check if the service is running

# Check if something is listening on the port
lsof -i :3000
ss -tlnp | grep 3000

# Check if the service is running
systemctl status postgresql
systemctl status mysql
docker ps  # For Docker services

Add retry logic for connections

const { setTimeout } = require('timers/promises');

async function connectWithRetry(connectFn, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await connectFn();
    } catch (error) {
      if (error.code === 'ECONNREFUSED' && attempt < maxRetries - 1) {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Connection refused. Retrying in ${delay}ms...`);
        await setTimeout(delay);
      } else {
        throw error;
      }
    }
  }
}

// Usage with a database
await connectWithRetry(async () => {
  const client = new Client({ connectionString: process.env.DATABASE_URL });
  await client.connect();
  return client;
});

Fix database connection

// PostgreSQL with pg
const { Client } = require('pg');

const client = new Client({
  host: '127.0.0.1',  // Use IP, not 'localhost' in some cases
  port: 5432,         // Verify port
  user: 'myuser',
  password: 'password',
  database: 'mydb'
});

client.connect()
  .then(() => console.log('Connected'))
  .catch(err => {
    if (err.code === 'ECONNREFUSED') {
      console.error('Database is not running. Start it with: sudo systemctl start postgresql');
    }
  });

Fix API connection

const axios = require('axios');

try {
  const response = await axios.get('http://localhost:3000/api/data');
} catch (error) {
  if (error.code === 'ECONNREFUSED') {
    console.error(`Cannot reach API server at ${error.address}:${error.port}`);
    console.error('Make sure the API server is running.');
  }
}

Fix in Docker Compose

# Use service names instead of localhost
services:
  app:
    build: .
    depends_on:
      db:
        condition: service_healthy
    environment:
      DB_HOST: db   # Service name, NOT localhost
      DB_PORT: 5432

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

Handle gracefully in Express middleware

app.use(async (req, res, next) => {
  try {
    await next();
  } catch (error) {
    if (error.code === 'ECONNREFUSED') {
      res.status(503).json({
        error: 'Service Unavailable',
        message: 'A required service is currently unavailable'
      });
    } else {
      next(error);
    }
  }
});