The MySQL error "Can't connect to local MySQL server through socket" (error 2002) means a client on the same machine tried to open MySQL's Unix socket file and failed. In practice there are only a few reasons: the server is not running, it is running but its socket is somewhere else, or the client is not allowed to open the file. The number in brackets at the end of the message tells you which one to check first.
A typical message:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
Why "localhost" means a socket
On Unix, a MySQL client can connect in two ways: through a Unix socket file in the file system, or over TCP/IP. According to the MySQL manual, the socket file is used if you do not specify a host name or if you specify the special host name localhost. So mysql -h localhost does not touch port 3306 at all, while mysql -h 127.0.0.1 does. That single detail explains a lot of confusing situations: "the port is open, but localhost does not work" is a socket problem, not a network problem.
Error 2002 is the socket case. If the client went over TCP, you would see error 2003, "Can't connect to MySQL server on 'host:port'". Both messages come from the client library, libmysql/errmsg.cc, and the last number in brackets is the operating system's error code.
Read the number in brackets
These are ordinary Linux errno values, and they narrow the search right away:
(2) ENOENT no file at that path: server not running, or wrong path
(13) EACCES the file or its directory is not accessible to this OS user
(111) ECONNREFUSED a socket file exists, but no server is listening on it
- (2) is the most common. Either mysqld is not running, or it created its socket at a different path than the one the client is looking at.
- (13) is about permissions: the socket file or one of its parent directories is not accessible to the user running the client. On systems with SELinux, the manual points to its SELinux section as well.
- (111) usually means a leftover socket file: the path exists, but the process that owned it is gone, typically after a crash.
Four checks that find the cause
# 1. Is the server running at all?
systemctl status mysql # or mysqld, depending on the package
ps aux | grep [m]ysqld
# 2. Which socket is the server really listening on?
ss -xlp | grep mysql
# 3. Which socket does the client try to use?
my_print_defaults client mysql
mysql --print-defaults
# 4. What does the server say about itself (over TCP)?
mysql -h 127.0.0.1 -P 3306 -u root -p -e "SELECT @@socket, @@port, @@skip_networking"
- No mysqld process means this is not a socket problem at all. The server is down, and the real question is why. Before restarting anything, read the error log (commands below the list).
- The server listens on a different socket.
ss -xlpshows the real path. Compare it with the path in the error message. - The client reads a different config.
my_print_defaults client mysqlprints the options themysqlclient gets from the[client]and[mysql]groups of the option files (see the my_print_defaults docs). A wrongsocket=line there, or none at all, is the usual culprit. - Ask the server. If TCP is enabled,
@@socketshows where the server put the file. If@@skip_networkingis 1, TCP is disabled and the socket is the only way in.
journalctl -u mysql -n 100 --no-pager
tail -n 100 /var/log/mysql/error.log # Debian/Ubuntu packages
tail -n 100 /var/log/mysqld.log # common on RPM-based systems
If the server is down, typical reasons in the log are a full disk, an InnoDB recovery error, a bad option in a freshly edited config file or a server killed by the OOM killer. Restarting without reading the log often just repeats the crash.
Where the socket lives
The compiled-in default for the socket system variable is /tmp/mysql.sock, and the manual adds that some distribution formats use a different directory, such as /var/lib/mysql for RPMs. The Debian/Ubuntu packages built from MySQL's own source set /var/run/mysqld/mysqld.sock in mysqld.cnf. That is why the error so often appears after something changes:
- a tarball, a source build or a second instance uses
/tmp/mysql.sock, while the client config points to the distro path, or the other way round; - someone changed
socket=under[mysqld]but not under[client]; - a cleanup job deleted
/tmp/mysql.sock. The manual mentions exactly this case and recommends either fixing the job or moving the socket out of/tmp.
The permanent fix is to put the same path in both groups:
# /etc/mysql/my.cnf or /etc/my.cnf: server and clients must agree
[mysqld]
socket = /var/run/mysqld/mysqld.sock
[client]
socket = /var/run/mysqld/mysqld.sock
The manual page on the socket file lists the other ways to tell clients the path: the --socket option and the MYSQL_UNIX_PORT environment variable. For a one-off connection, or while you are still investigating, any of these works:
mysql --socket=/var/lib/mysql/mysql.sock -u root -p # name the socket explicitly
mysql -h 127.0.0.1 --protocol=TCP -u app -p # skip the socket, use TCP
MYSQL_UNIX_PORT=/var/lib/mysql/mysql.sock mysqldump ... # environment variable
Switching to TCP is not always neutral. The server may match a different account, and the auth_socket plugin, which authenticates clients connecting through the Unix socket file, will not let you in over TCP at all. If root uses auth_socket, keep the socket and fix the path. When the connection works but the login fails, that is a different error; see our guide to MySQL error 1045.
Missing directory after a reboot
On modern systemd-based distributions /var/run is a link to /run, which lives in memory and is empty after every boot. The official Debian/Ubuntu service handles this: its pre-start script in mysql-helpers creates /var/run/mysqld with owner mysql and mode 0755 if it does not exist. If you start mysqld some other way, by hand, from a custom unit or in a container, nothing creates that directory, and the server cannot create its socket there. Check it and create it the same way:
ls -ld /var/run/mysqld /var/run/mysqld/mysqld.sock
# the official Debian/Ubuntu service creates the directory before start:
install -d -m0755 -o mysql -g mysql /var/run/mysqld
PHP, containers and other clients
PHP apps report the same problem as SQLSTATE[HY000] [2002]. The PDO_MYSQL documentation explains why: on Unix, a host name of localhost makes the connection go through a domain socket, and with mysqlnd the default path comes from pdo_mysql.default_socket, documented as /tmp/mysql.sock, although a PHP build can set a different default at compile time. Fix it in php.ini or name the socket in the DSN:
; php.ini
pdo_mysql.default_socket = /var/run/mysqld/mysqld.sock
mysqli.default_socket = /var/run/mysqld/mysqld.sock
// or in the DSN
$pdo = new PDO('mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=app', $user, $pass);
In containers the same rule causes a different failure. An app container that connects to localhost looks for a socket file inside its own file system, where there is none. Use the database service's host name or IP, which goes over TCP, or mount the socket directory into the container on purpose.
If connections work at first and then drop in the middle of queries, that is not 2002 either; "MySQL server has gone away" covers that case.
Key takeaways
- Error 2002 is a local socket connection failure.
localhostmeans the socket on Unix;127.0.0.1means TCP. - Read the errno in brackets: (2) server down or wrong path, (13) permissions, (111) leftover socket with no server behind it.
- If mysqld is not running, read the error log before restarting. The socket is just the symptom.
- Put the same
socket=in[mysqld]and[client], and point PHP'sdefault_socketto it. - Switching to TCP is a quick workaround, but
auth_socketaccounts only work over the socket.