MySQL Access Denied for User ‘root’@’localhost’: Fix It


You try to log in and MySQL turns you away:

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

On a fresh Ubuntu or Debian install, this usually is not a wrong password at all — MySQL 8 authenticates the root user through the operating system rather than a password, and the fix is simply to connect differently. If that is not your situation, the password can be reset without losing a single row.

Key Takeaways

  • On Ubuntu and Debian, MySQL root uses auth_socket by default — sudo mysql works while mysql -u root -p fails.
  • Check the authentication plugin before assuming the password is wrong.
  • Resetting the root password requires starting MySQL with authentication skipped, which is safe when done briefly.
  • While authentication is skipped the database accepts any connection, so stop the network listener during the reset.
  • ‘root’@’localhost’ and ‘root’@’%’ are different accounts with separate credentials.

Quick Fix

On Ubuntu and Debian, try connecting with sudo instead of a password. MySQL 8 authenticates root through the operating system by default, so no password exists to be wrong.

sudo mysql

Cause 1: auth_socket, Not a Wrong Password

This is the answer on most Debian-family systems. MySQL 8’s root account uses the auth_socket plugin, which authenticates based on the Unix user connecting rather than a password. Root gets in because it is root, not because it typed something.

So this works:

sudo mysql

While this fails, no matter what you type:

mysql -u root -p

Confirm which plugin is in use:

sudo mysql -e "SELECT user, host, plugin FROM mysql.user WHERE user='root';"

If the plugin column says auth_socket, that is your explanation. For interactive administration, keep it — it is more secure than a password. But applications cannot use it, so if a service needs database access, create a dedicated user for it rather than converting root:

sudo mysql -e "CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'strong-password'; GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost'; FLUSH PRIVILEGES;"

That is better practice anyway: the application gets rights to one database instead of everything.

If you specifically need password login for root, switch the plugin:

sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'your-new-password'; FLUSH PRIVILEGES;"

Cause 2: The Password Really Is Wrong

If sudo mysql also fails, or the plugin is not auth_socket, you need a reset. Stop the server first:

sudo systemctl stop mysql

Start it with authentication skipped, and with networking disabled so only local connections are possible:

sudo mysqld_safe --skip-grant-tables --skip-networking &

While this is running, MySQL accepts any connection with no credentials. The --skip-networking flag is what keeps that exposure local. Do not walk away from this state, and do not run it on a machine reachable from the internet without confirming the flag took effect.

Connect and reload the grant tables so the ALTER statement is permitted:

mysql -u root
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'your-new-password';
EXIT;

Now shut down the unprotected instance and start MySQL normally:

sudo pkill mysqld
sleep 5
sudo systemctl start mysql

Verify the new password works before you consider this done:

mysql -u root -p

Cause 3: Wrong Host in the Account

MySQL treats 'root'@'localhost' and 'root'@'%' as separate accounts with separate passwords. Connecting over TCP can match a different account than connecting over the socket, which produces a confusing failure where the same password works one way and not the other.

List the accounts:

sudo mysql -e "SELECT user, host FROM mysql.user;"

Note that -h 127.0.0.1 forces TCP and matches host-based accounts, while omitting it uses the local socket and matches localhost. If your application connects over TCP, make sure the account it uses actually permits that host.

Cause 4: An Application, Not You

If the error comes from an application rather than your shell, the credentials in its configuration are stale — commonly after a server migration or a password rotation. Test the exact values the app uses:

mysql -u appuser -p -h 127.0.0.1 appdb

If that fails, reset that user’s password rather than root’s:

sudo mysql -e "ALTER USER 'appuser'@'localhost' IDENTIFIED BY 'new-password'; FLUSH PRIVILEGES;"

Then update the application’s configuration to match, and restart it so it picks up the change.

Verify the Fix

Confirm you can connect and that privileges are intact:

mysql -u root -p -e "SELECT current_user(); SHOW DATABASES;"

Seeing your databases listed confirms both authentication and authorization are working. If you performed a reset, also confirm MySQL is running under systemd rather than the temporary instance:

systemctl status mysql

Prevent It From Recurring

Leave root on auth_socket for interactive use — there is no password to lose, and remote password attacks against root become impossible. Create a separate limited user for each application, scoped to the database it needs.

Store application credentials in one place your deployment reads, rather than copied into several config files where they drift apart. And after any password rotation, restart the services that use it; a stale connection pool produces this exact error hours after the change.

Frequently Asked Questions

Why does sudo mysql work but mysql -u root -p does not?

The root account uses the auth_socket plugin, which authenticates via the operating system user rather than a password. sudo makes you root at the OS level, which satisfies it. There is no password to enter.

Will resetting the root password delete my databases?

No. Resetting a password only changes an entry in the mysql.user table. Your databases and their contents are untouched. Take a backup first anyway if the data matters.

Is –skip-grant-tables dangerous?

Yes, while it is running, because MySQL accepts any connection without credentials. Always pair it with –skip-networking so only local connections are possible, and stop the instance as soon as the reset is done.

What is the difference between root@localhost and root@%?

They are separate accounts. localhost matches connections over the Unix socket, while % matches any host over TCP. Each has its own password and privileges, which is why one can work while the other fails.

Scroll to Top