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_socketand you're not the OSroot. - An app or ORM connecting over TCP as
rootwith a password:root@localhostis socket-authenticated and rejects the password login. - You actually want password login for root: the plugin has to be switched.
- MariaDB 10.4+:
rootships onunix_socketby 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 mysqlNo 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';. Apluginofauth_socketorunix_socketmeans the password is irrelevant. - Leave
rooton socket authentication and usesudo mysqlfor 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 needmysql_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.