MySQL

How to Fix "Error 1045 (28000): Access Denied for User 'root'@'localhost'"

4 min read by DebuggedIt

Quick answer

You try to connect to MySQL as root and get rejected outright, even with a password you're sure is correct. Error 1045 means MySQL received your connection...

You try to connect to MySQL as root and get rejected outright, even with a password you're sure is correct. Error 1045 means MySQL received your connection attempt and actively refused it based on username, password, or host matching β€” not a networking or server-down problem.

The Problem

A normal connection attempt fails immediately:

$ mysql -u root -p
Enter password:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

Sometimes it happens even with no password at all, which is its own clue:

$ mysql -u root
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

Why It Happens

MySQL authenticates a connection based on a specific combination of username, host, and credentials stored in its internal mysql.user table, matched against exactly how you're connecting. Error 1045 fires when that combination doesn't match anything MySQL has on record. Common causes:

  • The password is genuinely wrong, or was changed by another process (a package upgrade, a security hardening script, a teammate) without your knowledge.
  • On many modern installs (particularly Debian/Ubuntu package installs), root is configured to authenticate via the auth_socket plugin instead of a password β€” meaning a password login for root@localhost is rejected by design, and you're expected to connect via sudo mysql instead.
  • The user row that matches your connection is scoped to a different host than localhost β€” MySQL treats root@localhost, root@127.0.0.1, and root@% as entirely separate accounts with potentially different passwords or none at all.
  • A fresh MySQL install has a randomly generated temporary root password that needs to be reset, not guessed.

The Fix

If you're on a Debian/Ubuntu-style install where root uses auth_socket, connect using sudo instead of a password:

sudo mysql

Once connected, check which authentication plugin the root account is actually using:

SELECT user, host, plugin FROM mysql.user WHERE user='root';
+------+-----------+-------------+
| user | host      | plugin      |
+------+-----------+-------------+
| root | localhost | auth_socket |
+------+-----------+-------------+

If you'd rather switch root to password authentication so tools that expect a password login work correctly, change it explicitly:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_new_password';
FLUSH PRIVILEGES;

If you're just resetting a forgotten password rather than dealing with the auth_socket case, stop MySQL and start it in safe mode, skipping privilege checks temporarily:

sudo systemctl stop mysql
sudo mysqld_safe --skip-grant-tables --skip-networking &

Connect without a password and reset it:

mysql -u root
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'your_new_password';
FLUSH PRIVILEGES;

Restart MySQL normally afterward:

sudo systemctl stop mysql
sudo systemctl start mysql

Still Not Working?

If the password reset seems to succeed but you're still locked out, check whether multiple root rows exist for different hosts, since fixing root@localhost won't help if your client is actually connecting as root@127.0.0.1 (which MySQL treats as a distinct account):

SELECT user, host FROM mysql.user WHERE user='root';

If you see multiple rows with different hosts, update the credentials for the specific host you're actually connecting through, or check which one your client is using with:

mysql -u root -p -h 127.0.0.1

Comparing the behavior of connecting via localhost versus 127.0.0.1 explicitly often reveals that one works and the other doesn't, which points directly at a host-mismatch as the real cause rather than a wrong password.

It's also worth understanding why MySQL treats localhost differently from 127.0.0.1 in the first place, since this distinction causes confusion well beyond just this error. When you connect specifying localhost, the MySQL client library defaults to using a Unix socket file rather than a TCP/IP connection, bypassing the network stack entirely. Specifying 127.0.0.1 explicitly, on the other hand, forces a real TCP connection even though it's still local. These two connection methods can be authorized completely differently in the mysql.user table, which is exactly why an account might work through one and fail through the other even on the very same machine:

mysql -u root -p --protocol=TCP -h 127.0.0.1
mysql -u root -p --protocol=SOCKET -S /var/run/mysqld/mysqld.sock

If you manage multiple applications connecting to the same MySQL instance, it's worth standardizing on one connection method per environment and documenting it clearly, since silently switching between socket and TCP connections across different tools and scripts is a common source of exactly this kind of intermittent, hard-to-reproduce access error.