MySQL raises two connection errors before any authentication occurs:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)— the socket file does not exist or is not accessible (errno 2 = ENOENT, errno 111 = ECONNREFUSED)ERROR 2003 (HY000): Can't connect to MySQL server on 'hostname' (111)— TCP connection refused (errno 111 = ECONNREFUSED) or timed out (errno 110 = ETIMEDOUT)
Error 2002 is for Unix socket connections (local, --protocol=socket). Error 2003 is for TCP connections (--protocol=TCP, remote host, or 127.0.0.1).
Impact
These are pre-authentication errors — MySQL did not reject the credentials, it could not be reached at all. The application cannot open any connections. A 2002 or 2003 error at application startup prevents the service from starting. The same error during operation causes a full outage until the connection is restored.
Common Causes
Error 2002 (Socket)
mysqldis not running — the socket file is only created when the daemon starts- The socket file path in the client (
/var/run/mysqld/mysqld.sock) does not match the path mysqld is using (socketinmy.cnf) - Permissions on the socket file or its directory prevent the OS user from connecting
mysqldstarted but crashed before creating the socket
Error 2003 (TCP)
mysqldis not runningbind-addressinmy.cnfis set to127.0.0.1(localhost only), but the client is connecting from a different IP- A firewall (
iptables, security group,ufw) blocks port 3306 mysqldis listening on a non-standard port and the client uses 3306- The hostname in the connection string resolves to a different IP than expected (DNS issue)
skip-networkingis set inmy.cnf, disabling TCP entirely
Troubleshooting and Resolution Steps
Check whether
mysqldis running:# systemd systemctl status mysql systemctl status mysqld # or directly pgrep -a mysqld ps aux | grep mysqldIf not running, check the error log:
journalctl -u mysql --since "1 hour ago" # or cat /var/log/mysql/error.log | tail -50Start mysqld if it is stopped:
systemctl start mysql # or on older systems service mysql startVerify the socket file location:
# What path is mysqld using? mysql -u root -p -e "SHOW VARIABLES LIKE 'socket'" # or from the configuration mysqld --verbose --help 2>/dev/null | grep "socket" # What socket path does the client default to? mysql --print-defaults | grep socket # Does the socket file exist? ls -la /var/run/mysqld/mysqld.sockIf the paths differ, specify the socket explicitly:
mysql -u root -p --socket=/path/to/actual.sockOr update the client's
[client]section inmy.cnf:[client] socket = /var/run/mysqld/mysqld.sockCheck
bind-addressfor TCP connection refusals:grep -r "bind.address\|bind-address\|skip.networking" /etc/mysql/ /etc/my.cnf 2>/dev/nullSHOW VARIABLES LIKE 'bind_address'; SHOW VARIABLES LIKE 'skip_networking';To allow remote connections, set
bind-address = 0.0.0.0(all interfaces) or a specific interface IP:[mysqld] bind-address = 0.0.0.0 # listen on all interfacesThen restart MySQL and ensure the user account grants access from the remote host (see error 1045).
Verify which port and address mysqld is actually listening on:
ss -tlnp | grep mysql netstat -tlnp | grep 3306 # Look for: 0.0.0.0:3306 or 127.0.0.1:3306127.0.0.1:3306means only local connections are accepted.0.0.0.0:3306means all interfaces.Test the TCP connection from the client machine:
# Test reachability (no MySQL protocol — just TCP) nc -zv mysql-host 3306 telnet mysql-host 3306 # or curl -v telnet://mysql-host:3306 # Expected: Connection to mysql-host 3306 port [tcp/*] succeeded!If this fails, the problem is the firewall or
bind-address, not MySQL itself.Check and open the firewall:
# UFW (Ubuntu) ufw allow from 10.0.1.0/24 to any port 3306 ufw status # iptables iptables -I INPUT -s 10.0.1.0/24 -p tcp --dport 3306 -j ACCEPT # AWS Security Group: add inbound rule TCP port 3306 from the application's CIDR # GCP Firewall: gcloud compute firewall-rules create allow-mysql --allow tcp:3306For cloud databases (RDS, Aurora, Cloud SQL), check the security group / VPC:
- The RDS instance's security group must have an inbound rule allowing TCP 3306 from the application's security group or CIDR.
- The application and database must be in the same VPC, or VPC peering / VPN must be configured.
- Check "Publicly accessible" setting — if
No, the database is only reachable within the VPC.
Connect to
127.0.0.1instead oflocalhostwhen TCP is needed but socket is the default:# 'localhost' in MySQL clients means socket by default mysql -u root -p -h 127.0.0.1 # forces TCP mysql -u root -p -h localhost # uses socketIn connection strings:
# Socket (localhost) mysql://root:pass@localhost/mydb # TCP (127.0.0.1) mysql://root:pass@127.0.0.1/mydbRemove
skip-networkingif it was accidentally set:[mysqld] # skip-networking # comment out or removeThen restart MySQL.
skip-networkingdisables all TCP connections and leaves only socket connections available.Check socket file permissions:
ls -la /var/run/mysqld/ # Expected: srwxrwxrwx 1 mysql mysql ... mysqld.sock # The socket must be writable by the connecting user or world-writableIf the
mysqlCLI runs as root and the socket is only accessible tomysqluser, run:chmod 777 /var/run/mysqld/mysqld.sock # temporary fix # Better: run the client as the mysql OS user, or check my.cnf socket group
Additional Information
- Error 2002 errno 2 (ENOENT) means the socket file does not exist — mysqld is not running or used a different socket path. Errno 111 (ECONNREFUSED) means the socket exists but nothing is listening on it.
- Error 2003 errno 111 (ECONNREFUSED) means the TCP port is not open on the target host. Errno 110 (ETIMEDOUT) means the connection attempt timed out — typically a firewall drops the packets without sending a RST.
- In containerized deployments (Docker, Kubernetes), MySQL and the application must be on the same Docker network or Kubernetes cluster. Referencing
localhostfrom inside the application container points to the container itself, not to a MySQL container. - Amazon RDS Proxy, ProxySQL, and HAProxy each have their own listening address — check their configuration if the connection goes through a proxy.
Frequently Asked Questions
Q: MySQL is running but I still get error 2002 from the CLI. Why?
A: The CLI is connecting via socket and the socket path in the client's my.cnf differs from where mysqld wrote the socket file. Run mysql --print-defaults | grep socket and mysql -e "SHOW VARIABLES LIKE 'socket'" to compare.
Q: The application connects fine on the same host but fails from another server. Why?
A: bind-address = 127.0.0.1 restricts MySQL to local connections only. Set bind-address = 0.0.0.0 in my.cnf and restart, then verify the firewall allows port 3306 from the application server's IP.
Q: I changed bind-address but still get the error. Why?
A: The change requires a MySQL restart. Verify with ss -tlnp | grep 3306 that MySQL is now listening on 0.0.0.0:3306 instead of 127.0.0.1:3306.
Q: After an OS reboot, MySQL fails to start because the socket file has wrong permissions. Why?
A: Some installations write the socket to a tmpfs directory (/var/run) that is cleared on reboot. The mysql.service systemd unit or an init script recreates the directory on startup. Check systemctl status mysql for the startup error. Running systemd-tmpfiles --create or adjusting /etc/tmpfiles.d/mysql.conf fixes this.
Q: How do I connect to MySQL from a Docker container?
A: Use Docker networking. If MySQL runs in a container named mysql-db on the default bridge network, connect to it using the container name as the hostname — but only if both containers are on the same user-defined network (docker network create). Or expose MySQL's port and connect via the host IP.