Incident Response

MySQL "Can't connect to local MySQL server through socket" (Error 2002): Fixes

The mysql client, a cron job or a PHP app suddenly says it cannot reach the local server through a .sock file. Usually the server is down, or the client and server disagree about where the socket is. The number in brackets at the end tells you which.

· 12 min read · AG Data Team

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

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"
  1. 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).
  2. The server listens on a different socket. ss -xlp shows the real path. Compare it with the path in the error message.
  3. The client reads a different config. my_print_defaults client mysql prints the options the mysql client gets from the [client] and [mysql] groups of the option files (see the my_print_defaults docs). A wrong socket= line there, or none at all, is the usual culprit.
  4. Ask the server. If TCP is enabled, @@socket shows where the server put the file. If @@skip_networking is 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:

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
Do not "fix" 2002 with chmod 777. Opening the socket directory or the data directory to everyone hides the real problem and gives every local user a path to the server. Find out which user runs the client, which user owns the socket, and fix the path or the group membership instead.

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

MySQL Connections Linux Troubleshooting
Work with us

MySQL down and the app can't connect?

If MySQL will not start or clients cannot reach it, we can help right away: we find why, bring the server back and fix the configuration so it stays up. Tell us what you see in the logs.

Get in touch More from the blog