Skip to main content

ERROR 1698 (28000): Access Denied for User 'root'@'localhost' in MySQL

Error Message

ERROR 1698 (28000): Access denied for user 'root'@'localhost'

You may hit the same code for a non-root account, and on MariaDB the wording is identical:

ERROR 1698 (28000): Access denied for user 'admin'@'localhost'

What Triggers This Error

1698 reads like a wrong-password error. It usually isn't. The giveaway is that it appears with no (using password: YES) suffix, unlike ERROR 1045. That suffix is missing because the account isn't checking a password at all.

On Debian, Ubuntu, and most MariaDB packages, the root account is created with the auth_socket plugin (called unix_socket on MariaDB). That plugin ignores any password you type and instead checks the operating-system user running the client. If your OS user name matches the MySQL user name, you're in. If it doesn't, you get 1698. So mysql -u root -p typed as a normal Linux user fails every time, no matter what password you enter.

The fix depends on which situation you're in:

  • Fresh install, connecting from the shell as a non-root OS user: the account is on auth_socket and you're not the OS root.
  • An app or ORM connecting over TCP as root with a password: root@localhost is socket-authenticated and rejects the password login.
  • You actually want password login for root: the plugin has to be switched.
  • MariaDB 10.4+: root ships on unix_socket by default; the switch syntax differs slightly.

Fix by Scenario

Connecting from the shell after a fresh install

The account works exactly as designed. Connect as the OS root user and the socket check passes:

sudo mysql

No password prompt, no 1698. This is the intended path on Ubuntu 24.04 / MySQL 8.0 and 8.4 installs, and it's the one most tutorials skip.

An application connects as root with a password

Don't repurpose root for this. root@localhost stays on socket auth; create a dedicated account with a real password and grant only the privileges the app needs. If the new account then fails with a database-level ERROR 1044, the grant is missing or scoped to the wrong host.

CREATE USER 'app_user'@'%' IDENTIFIED BY 'a-strong-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_user'@'%';
FLUSH PRIVILEGES;

Point the connection string at app_user. The error disappears because that account authenticates by password, not by OS identity.

You want root itself to log in with a password

Connect with sudo mysql, then switch the plugin. On MySQL 8.0 / 8.4:

ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'a-strong-password';
FLUSH PRIVILEGES;

Use mysql_native_password instead if an older client can't speak caching_sha2_password. After this, mysql -u root -p works, and sudo mysql will fail unless you pass -p (for example, sudo mysql -p).

MariaDB 10.4 and later

MariaDB names the plugin unix_socket. Connect with sudo mysql and either switch to password auth or enable both methods:

ALTER USER 'root'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD('a-strong-password');
FLUSH PRIVILEGES;

Prevention

  • Check how an account authenticates before debugging passwords: SELECT user, host, plugin FROM mysql.user WHERE user = 'root';. A plugin of auth_socket or unix_socket means the password is irrelevant.
  • Leave root on socket authentication and use sudo mysql for local admin work. It's harder to brute-force than a password.
  • Give every application its own password-based account scoped to one database, never root.
  • Match the authentication plugin to your client. New clients handle caching_sha2_password; older drivers may still need mysql_native_password.

Sharing one root login across a team is how credentials leak and changes go untracked. Bytebase puts a review-and-access layer in front of the database, so engineers connect through their own identity with scoped permissions instead of a shared superuser. See Bytebase database permissions.

Explore the standard for database development