How To Guide

How to Fix ECONNREFUSED: Step-by-Step Diagnostic Guide

Fix ECONNREFUSED errors fast. Diagnose whether the process is running, listening on the right port and interface, and check firewalls plus Docker.

How to Fix ECONNREFUSED

ECONNREFUSED is one of the most misread errors in networking. It does not mean the network is down, DNS is broken, or a firewall is silently dropping packets. It means your TCP SYN reached the target host, and the target replied with a RST (reset) packet. Translation: the machine is up, but nothing is listening on that port — or something is listening but actively rejected the connection.

Because the packet round-trip actually completes, ECONNREFUSED is fast (no timeout). That is your biggest clue: this is a service problem, not a network problem. Work through the checks below in order.

Step 1: Is the target process actually running?

Before touching networking, confirm the service you expect to answer is alive.

# Linux with systemd
systemctl status postgresql
systemctl status nginx

# Generic process check
ps aux | grep -i node
pgrep -a postgres

# Docker
docker ps
docker ps -a  # includes stopped containers
docker logs <container> --tail 50

If the process crashed on startup, you will see it in docker ps -a as Exited or in journalctl -u <service> -n 100. Fix the crash first — nothing else matters until the process stays up.

Step 2: Is it listening on the port you expect?

A running process is not the same as a listening socket. Verify the port is bound.

# Modern Linux (preferred)
ss -tlnp | grep :5432

# Older Linux / BSD
netstat -tlnp | grep :5432

# macOS
lsof -nP -iTCP:5432 -sTCP:LISTEN

# Windows PowerShell
Get-NetTCPConnection -LocalPort 5432 -State Listen

No output means nothing is listening. Check the app's config (wrong port in .env? default overridden?) and its startup logs. A common trap: the process is up but crashed after logging “Server started” — always confirm with ss, not with the app log.

Step 3: Is it listening on the RIGHT interface?

This is the single most common cause of ECONNREFUSED from a remote client. A service can bind to:

  • 127.0.0.1 (loopback only) — reachable only from the same host
  • 0.0.0.0 or :: — reachable from any interface
  • A specific IP like 192.168.1.10 — reachable only via that NIC
ss -tlnp
# LISTEN 0 128 127.0.0.1:5432   ← only localhost
# LISTEN 0 128 0.0.0.0:5432     ← all interfaces
# LISTEN 0 128 [::]:5432        ← all IPv6 interfaces

If you see 127.0.0.1:PORT and you are connecting from another machine or a Docker container, the kernel will reject the SYN with RST — producing ECONNREFUSED. Fix it in the app config:

  • Postgres: listen_addresses = '*' in postgresql.conf
  • Redis: bind 0.0.0.0 (and set a password!)
  • Node/Express: app.listen(3000, '0.0.0.0') instead of the default localhost
  • MySQL: comment out bind-address = 127.0.0.1

Step 4: Firewall or cloud security group

Once the port binds to 0.0.0.0 and you still get ECONNREFUSED locally but a timeout remotely, that is a firewall — different symptom, different fix. But some firewalls (and hosted proxies) issue TCP resets instead of drops, which surfaces as ECONNREFUSED.

# ufw / Debian
sudo ufw status
sudo ufw allow 5432/tcp

# firewalld / RHEL
sudo firewall-cmd --list-all
sudo firewall-cmd --add-port=5432/tcp --permanent && sudo firewall-cmd --reload

# iptables
sudo iptables -L -n -v

On AWS / GCP / Azure, check the instance's security group / firewall rules in the console — inbound rules for the port from your source CIDR.

Step 5: SELinux or AppArmor

On RHEL/CentOS/Fedora, SELinux can block a daemon from binding to a non-standard port even when everything else is correct.

# Check for recent SELinux denials
sudo ausearch -m avc -ts recent
sudo journalctl -t setroubleshoot -n 50

# Allow a service to bind a custom port (example: httpd on 8080)
sudo semanage port -a -t http_port_t -p tcp 8080

On Ubuntu, check sudo aa-status and /var/log/syslog for apparmor="DENIED".

Docker-specific traps

Docker networking generates ECONNREFUSED more than any other layer. Three cases dominate:

Container trying to reach a service on the host

Inside a container, localhost is the container itself, not the host. If your app connects to localhost:5432 to reach Postgres running on the host, the container's loopback has nothing listening — instant ECONNREFUSED.

  • On Docker Desktop (macOS & Windows): use host.docker.internal instead of localhost.
  • On Linux: add --add-host=host.docker.internal:host-gateway to docker run, or use the bridge IP (usually 172.17.0.1), or run with --network=host.

Container-to-container on the same host

Containers must share a Docker network and connect by service name, not localhost. In docker-compose.yml, connect from the api service to db:5432 — not localhost:5432.

Port bound to 127.0.0.1 on the host

Publishing with -p 127.0.0.1:5432:5432 binds only to host loopback; remote clients get ECONNREFUSED. Use -p 5432:5432 to bind on all interfaces.

Quick recap

Run the checks in order — process, port, interface, firewall, MAC layer. Nine times out of ten, ECONNREFUSED ends at step 3: the service is bound to 127.0.0.1 and you are connecting from somewhere else. Fix the bind address, restart the service, and move on.

econnrefused connection refused port not listening ss -tlnp docker networking host.docker.internal firewall 0.0.0.0 vs 127.0.0.1

Explore 300+ Free Tools

Utilko has tools for developers, writers, designers, students, and everyday users — all free, all browser-based.