Fix: MySQL ERROR 2002 (HY000): Can't connect to local MySQL server through socket
The Error
You try to connect to MySQL and get:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)Or one of these variations:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (13)The (2) at the end means “No such file or directory” — the socket file doesn’t exist. The (13) means “Permission denied” — the socket file exists but your user can’t access it. Both point to the same underlying problem: the MySQL client can’t communicate with the MySQL server through its Unix socket.
Why This Happens
When you connect to MySQL on Linux or macOS without specifying a hostname (e.g., just mysql -u root), the client doesn’t use TCP. Instead, it connects through a Unix domain socket — a special file on disk that allows inter-process communication. This is faster than TCP because it bypasses the network stack entirely.
The socket file is created by the MySQL server when it starts and removed when it stops. Its default location varies by distribution:
- Debian/Ubuntu:
/var/run/mysqld/mysqld.sock - RHEL/CentOS/Fedora:
/var/lib/mysql/mysql.sock - macOS (Homebrew):
/tmp/mysql.sock - SUSE/OpenSUSE:
/var/run/mysql/mysql.sock
ERROR 2002 means either:
- MySQL isn’t running, so the socket file was never created (or was removed on shutdown).
- The socket file exists, but the client is looking in the wrong place. The server and client have different ideas about where the socket lives.
- The socket file or its directory has wrong permissions, so the client can’t access it.
- The socket file was deleted while MySQL was still running (e.g., by an overly aggressive
tmpwatchorsystemd-tmpfiles). - Something external is blocking access to the socket file (AppArmor, SELinux, or container isolation).
Fix 1: Start the MySQL Service
The most common cause. MySQL isn’t running, so the socket file doesn’t exist.
Linux (systemd):
sudo systemctl start mysqlOn RHEL/CentOS/Fedora, the service name is mysqld:
sudo systemctl start mysqldCheck the status:
sudo systemctl status mysqlIf it’s not enabled to start on boot:
sudo systemctl enable mysqlLinux (older init systems):
sudo service mysql startmacOS (Homebrew):
brew services start mysqlAfter starting, verify the socket file was created:
ls -la /var/run/mysqld/mysqld.sockThen test the connection:
mysql -u root -pIf the service fails to start, skip ahead to Fix 9 to check the error log.
Fix 2: Fix the Socket Path in my.cnf
The MySQL client and server both read the socket path from configuration files. If they disagree about the path, the server creates the socket in one location while the client looks for it in another.
Find which config files MySQL is reading:
mysql --help | grep -A 1 "Default options"This shows something like:
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnfCheck the socket path configured for both [mysqld] (server) and [client] (client):
grep -r "socket" /etc/my.cnf /etc/mysql/ 2>/dev/nullMake sure both sections use the same path. Edit your my.cnf:
[mysqld]
socket=/var/run/mysqld/mysqld.sock
[client]
socket=/var/run/mysqld/mysqld.sockIf you just want to connect right now without changing the config, pass the socket path directly:
mysql -u root -p --socket=/var/run/mysqld/mysqld.sockTo find where the running MySQL server actually created the socket:
sudo find / -name "mysql*.sock" -type s 2>/dev/nullRestart MySQL after changing the config:
sudo systemctl restart mysqlFix 3: Recreate the Socket Directory
On some systems, the socket directory (e.g., /var/run/mysqld/) doesn’t survive a reboot because /var/run is mounted as a tmpfs. If the directory is missing, MySQL can’t create the socket file and fails to start.
Check if the directory exists:
ls -la /var/run/mysqld/If it doesn’t exist, create it with the correct ownership:
sudo mkdir -p /var/run/mysqld
sudo chown mysql:mysql /var/run/mysqld
sudo chmod 755 /var/run/mysqldThen restart MySQL:
sudo systemctl restart mysqlTo make this permanent across reboots, create a tmpfiles.d configuration:
echo "d /var/run/mysqld 0755 mysql mysql -" | sudo tee /etc/tmpfiles.d/mysql.confFix 4: Fix Permissions on the Socket File
If the error ends with (13) instead of (2), the socket file exists but your user can’t access it. This is a permissions problem, similar to file and socket permission issues in Docker.
Check the socket file permissions:
ls -la /var/run/mysqld/mysqld.sockThe socket should be owned by the mysql user and be readable/writable by others:
srwxrwxrwx 1 mysql mysql 0 Apr 17 10:00 /var/run/mysqld/mysqld.sockIf the permissions are too restrictive, fix them:
sudo chmod 777 /var/run/mysqld/mysqld.sockAlso check the directory permissions. The user running the MySQL client needs execute permission on every directory in the path:
sudo chmod 755 /var/run/mysqldIf the permissions keep resetting, check the my.cnf for a restrictive socket permission setting or examine whether AppArmor/SELinux is interfering (see Fix 7).
Fix 5: Connect via TCP Instead of the Socket
If you need to connect immediately and can’t fix the socket issue right away, bypass the socket entirely by forcing a TCP connection:
mysql -u root -p --protocol=tcpOr use 127.0.0.1 instead of localhost. When you use localhost, MySQL uses the Unix socket. When you use 127.0.0.1, it uses TCP:
mysql -u root -p -h 127.0.0.1For application connection strings, use 127.0.0.1 instead of localhost:
mysql://root:password@127.0.0.1:3306/mydbIn PHP (php.ini or your app config):
mysqli.default_host = 127.0.0.1This is a valid workaround, but it’s slightly slower than socket connections for local access. For remote connections, TCP is the only option anyway. Make sure MySQL is listening on TCP by checking:
sudo ss -tlnp | grep 3306If nothing shows up, ensure skip-networking is not enabled in my.cnf:
# Remove or comment out this line:
# skip-networkingFix 6: Fix a Deleted Socket File (Without Restarting)
If something deleted the socket file while MySQL is still running (for example, tmpwatch or systemd-tmpfiles cleaning up /tmp or /var/run), MySQL is running but unreachable.
Check if MySQL is actually running:
ps aux | grep mysqldIf it is running, the quickest fix is to restart MySQL so it recreates the socket:
sudo systemctl restart mysqlTo prevent tmpwatch or systemd-tmpfiles from cleaning up the socket in the future, exclude the directory. For systemd-tmpfiles, create a configuration:
echo "x /var/run/mysqld/*" | sudo tee /etc/tmpfiles.d/mysql-protect.confFor tmpwatch on RHEL/CentOS, edit /etc/cron.daily/tmpwatch and add an exclusion for the socket directory.
Fix 7: AppArmor or SELinux Blocking Access
Security frameworks like AppArmor (Ubuntu/Debian) and SELinux (RHEL/CentOS/Fedora) can silently block MySQL from creating or accessing the socket file.
SELinux:
Check if SELinux is blocking MySQL:
sudo ausearch -m AVC -ts recent | grep mysqlOr check the audit log:
sudo grep mysql /var/log/audit/audit.log | tail -20Temporarily set SELinux to permissive to test:
sudo setenforce 0
sudo systemctl restart mysqlIf MySQL works in permissive mode, generate a proper SELinux policy:
sudo ausearch -c 'mysqld' --raw | audit2allow -M mysql_local
sudo semodule -i mysql_local.ppThen re-enable enforcing mode:
sudo setenforce 1AppArmor:
Check if AppArmor is restricting MySQL:
sudo aa-status | grep mysqlIf the MySQL profile is in enforce mode, temporarily switch it to complain mode:
sudo aa-complain /usr/sbin/mysqld
sudo systemctl restart mysqlIf that fixes it, update the AppArmor profile to allow the socket path and then re-enforce:
sudo aa-enforce /usr/sbin/mysqldFix 8: Docker MySQL Socket Issues
When running MySQL in a Docker container, the socket file exists inside the container, not on the host. A client running on the host can’t access it.
Connect to Docker MySQL via TCP:
mysql -u root -p -h 127.0.0.1 -P 3306Make sure you exposed the port in your docker run command:
docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=secret mysql:8Share the socket file with the host:
Mount a volume for the socket:
docker run -d --name mysql \
-v /var/run/mysqld:/var/run/mysqld \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8Connecting from another container (docker-compose):
Use the service name as the hostname, just as you would with PostgreSQL container networking:
services:
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: secret
ports:
- "3306:3306"
app:
build: .
environment:
DATABASE_URL: mysql://root:secret@db:3306/mydb
depends_on:
- dbThe hostname inside the container is db, not localhost.
Fix 9: MySQL Crashed — Check the Error Log
If MySQL was running and suddenly stopped, the socket file disappears and you get ERROR 2002. Check the error log to find out why it crashed:
# Debian/Ubuntu
sudo tail -100 /var/log/mysql/error.log
# RHEL/CentOS/Fedora
sudo tail -100 /var/log/mysqld.log
# Or use journalctl
sudo journalctl -u mysql --no-pager -n 100Common crash causes:
- Disk full. MySQL can’t write and shuts down. Free up space:
df -h- Out of memory. The OOM killer terminated MySQL. Check:
sudo dmesg | grep -i "oom" | grep mysqlReduce MySQL memory usage in my.cnf:
[mysqld]
innodb_buffer_pool_size = 256M
key_buffer_size = 32M- Corrupted InnoDB tablespace. Look for
InnoDB: corruptionmessages in the error log. Start MySQL in recovery mode:
[mysqld]
innodb_force_recovery = 1Start with 1 and increase up to 6 if needed. Dump your data and rebuild once it starts.
- Stale PID file. If MySQL didn’t shut down cleanly, a PID file may prevent it from starting:
sudo rm /var/run/mysqld/mysqld.pid
sudo systemctl start mysqlOnly remove the PID file if you’ve confirmed MySQL is not running with ps aux | grep mysqld.
Fix 10: tmpdir Full or Unwritable
MySQL uses a temporary directory for sorting, temporary tables, and other operations. If this directory is full or unwritable, MySQL may fail to start.
Check the configured tmpdir:
mysql -u root -p -e "SHOW VARIABLES LIKE 'tmpdir';"If you can’t connect, check the config:
grep tmpdir /etc/mysql/my.cnf /etc/my.cnf 2>/dev/nullCheck if the tmpdir has space and correct permissions:
df -h /tmp
ls -la /tmpIf /tmp is full, clean it up or point MySQL to a different directory:
[mysqld]
tmpdir = /var/tmpRestart MySQL after changing this.
Fix 11: Multiple MySQL Installations Conflicting
Having multiple MySQL installations (or MySQL alongside MariaDB) can cause socket conflicts. Each instance may try to use a different socket path, or one installation’s client may try to connect to another installation’s server.
Check for multiple installations:
# Debian/Ubuntu
dpkg -l | grep -i mysql
dpkg -l | grep -i mariadb
# RHEL/CentOS
rpm -qa | grep -i mysql
rpm -qa | grep -i mariadbCheck for multiple running instances:
ps aux | grep mysqldIf multiple instances are running, each should have a unique socket path, port, and data directory in its my.cnf. To connect to a specific instance, use its socket:
mysql -u root -p --socket=/var/run/mysqld/mysqld.sock
mysql -u root -p --socket=/var/run/mysqld/mysqld2.sockIf you only need one installation, remove the conflicting one. On Debian/Ubuntu, MariaDB and MySQL use the same socket path by default, so they can’t run simultaneously without reconfiguration.
Fix 12: macOS Homebrew-Specific Issues
On macOS with Homebrew, MySQL uses /tmp/mysql.sock by default, but several things can go wrong.
Check if MySQL is running:
brew services list | grep mysqlStart MySQL:
brew services start mysqlCheck where the socket actually is:
ls -la /tmp/mysql.sockIf the socket is missing but MySQL is running, check if Homebrew installed MySQL with a custom socket path:
cat /opt/homebrew/etc/my.cnf 2>/dev/null
cat /usr/local/etc/my.cnf 2>/dev/nullCommon macOS fix — create a symlink:
If your client expects the socket at /tmp/mysql.sock but MySQL creates it elsewhere:
sudo ln -s /opt/homebrew/var/mysql/mysqld.local.sock /tmp/mysql.sockFix for macOS Sequoia and later:
Recent macOS versions may clean up /tmp more aggressively. If the socket keeps disappearing, configure MySQL to use a different directory:
[mysqld]
socket=/opt/homebrew/var/mysql/mysqld.sock
[client]
socket=/opt/homebrew/var/mysql/mysqld.sockIf you previously installed MySQL via the official DMG and now use Homebrew (or vice versa), conflicting configurations may exist. Check for config files in multiple locations:
ls -la /etc/my.cnf /usr/local/etc/my.cnf /opt/homebrew/etc/my.cnf ~/.my.cnf 2>/dev/nullFix 13: WSL (Windows Subsystem for Linux) Specific Issues
Running MySQL inside WSL has unique challenges because WSL doesn’t use systemd by default (WSL 1 and older WSL 2).
Start MySQL manually on WSL without systemd:
sudo service mysql startOr start the daemon directly:
sudo mysqld_safe &Check if MySQL is running:
ps aux | grep mysqldSocket path issues on WSL:
The socket directory may not exist after a WSL restart. Create it:
sudo mkdir -p /var/run/mysqld
sudo chown mysql:mysql /var/run/mysqld
sudo service mysql startWSL 2 with systemd enabled:
If you’ve enabled systemd in WSL 2 (via /etc/wsl.conf), the standard systemctl commands work:
sudo systemctl start mysqlConnecting from Windows to MySQL inside WSL:
From Windows, connect via TCP to WSL’s IP address:
mysql -u root -p -h 127.0.0.1 -P 3306The socket file is not accessible from Windows because it’s inside the WSL filesystem. Always use TCP for cross-system connections.
Connecting from WSL to MySQL on Windows:
If MySQL is installed on Windows (not WSL), connect via TCP using the Windows host IP:
mysql -u root -p -h $(hostname).local -P 3306Still Not Working?
MySQL starts but the socket disappears after a few seconds
This usually means MySQL starts, encounters an error, and shuts down immediately. The socket exists briefly but is removed on shutdown. Check the error log — the real error is there:
sudo tail -50 /var/log/mysql/error.logCommon causes: wrong file ownership on the data directory, InnoDB log file size mismatch after a configuration change, or insufficient file descriptors.
Connection works as root but not as your user
If sudo mysql -u root works but mysql -u root doesn’t, the issue is file permissions on the socket or its parent directory. Your regular user needs read and execute access to /var/run/mysqld/. This is similar to other permission-denied issues in Bash where the current user lacks the necessary access rights.
ERROR 1045 instead of ERROR 2002
If you’ve fixed the socket issue but now see ERROR 1045 (28000): Access denied for user, that’s a separate authentication problem. The connection itself is working — your credentials are wrong. See Fix: MySQL Access Denied for User for solutions.
The socket file exists but connections still fail
If the socket file is present and has correct permissions but connections still fail, the file may be stale (left over from a crashed MySQL instance). Remove it and restart:
sudo rm /var/run/mysqld/mysqld.sock
sudo systemctl restart mysqlApplication-specific connection issues
Some applications have their own MySQL socket configuration separate from the system default:
- PHP: Check
pdo_mysql.default_socketandmysqli.default_socketinphp.ini. - Python (mysqlclient): Pass
unix_socketin your connect call or set it in amy.cnfthat your app reads. - Ruby on Rails: Set
socketinconfig/database.yml. - WordPress: Set
DB_HOSTinwp-config.phptolocalhost:/var/run/mysqld/mysqld.sock.
Nothing works and you need to connect to a remote database
If you’re actually trying to reach a MySQL server on another machine, the socket approach won’t work at all. Use TCP with the remote host’s IP or hostname:
mysql -u root -p -h 192.168.1.100 -P 3306Make sure the remote server’s bind-address in my.cnf allows connections from your IP, and that the firewall permits traffic on port 3306. This is conceptually the same as troubleshooting remote connection issues with MongoDB or Redis — verify the service is listening, the bind address is correct, and the firewall is open.
Related: If you’re troubleshooting other database connection problems, see Fix: PostgreSQL Connection Refused and Fix: MySQL Access Denied for User. For Docker socket and permission issues, see Fix: Docker Permission Denied. If your connection string is coming from environment variables that aren’t loading, see Fix: Bash Permission Denied.
Related Articles
Fix: Access denied for user 'root'@'localhost' (MySQL ERROR 1045)
How to fix MySQL 'ERROR 1045 (28000): Access denied for user root@localhost (using password: YES/NO)' on Linux, macOS, Windows, and Docker. Covers password reset, auth plugin issues, skip-grant-tables recovery, MySQL 8 vs 5.7 differences, and host mismatches.
Fix: MySQL Too Many Connections – Error 1040
How to fix the MySQL error 1040 'Too many connections' by adjusting max_connections, fixing connection leaks, and optimizing connection pooling.
Fix: psql: error: connection to server refused (PostgreSQL)
How to fix 'could not connect to server: Connection refused', 'psql: error: connection to server at localhost port 5432 failed', and other PostgreSQL connection refused errors on Linux, macOS, Windows, and Docker.
Fix: Docker Volume Permission Denied – Cannot Write to Mounted Volume
How to fix Docker permission denied errors on mounted volumes caused by UID/GID mismatch, read-only mounts, or SELinux labels.