MySQL ERROR 1045 "Access Denied for User 'root'@'localhost'": Every Fix on Amazon Linux 2023, Docker and RDS
ERROR 1045 (28000): Access denied for user 'root'@'localhost' means MySQL found an account that could match you, but the user name and password didn't. The ending tells you which half to fix: (using password: NO) means no password was sent at all, and (using password: YES) means one was sent and it was wrong. Use the one that works for your setup, or reset it: on RDS with one command, and on your own server with --skip-grant-tables. But check three traps first, because they cause most of these errors and none of them is a forgotten password. On Amazon Linux 2023, MariaDB's root has no password at all; you sign in with sudo mysql, and following a MySQL tutorial's ALTER USER root ... IDENTIFIED BY there locks sudo mysql out. In Docker, changing MYSQL_ROOT_PASSWORD doesn't change the password of a database that already exists. And a forgotten ~/.my.cnf can send an old password without you typing one. This page shows each case with its exact message, and the fix that matches.
Ethan, a developer, runs the booking app for his friend Jake's phone repair shop on an EC2 server with MariaDB. A security checklist told him to "set a root password", so he ran the command from a MySQL tutorial. The next morning, sudo mysql, which had worked for months, said ERROR 1045.
New to these terms? MariaDB is the MySQL-compatible database that Amazon Linux 2023 installs; its mysql command and error messages work the same way. Docker runs MySQL in a container, with its data kept in a volume.
Read the message: three versions, three meanings
These three lines look nearly the same, and each one needs a different fix:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
ERROR 1045 (28000): Access denied for user 'app'@'localhost' (using password: YES)
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
| Message | What it means | Fix |
|---|---|---|
| 1045 ... (using password: NO) | No password was sent, and this account needs one | Add -p, or, for a lost one, reset it |
| 1045 ... (using password: YES) | A password was sent and it didn't match | Check the password, the shell, ~/.my.cnf and anonymous accounts |
| 1698 for root, no "using password" | The account signs in by system identity, not by password (MariaDB) | Use sudo mysql |
| 1130 "is not allowed to connect" | No account exists for the host you came from | Create the account for that host |
One thing that's always true: the 'localhost' part is where MySQL thinks you came from, not where the account was created. An account made for '%' still shows up as 'app'@'localhost' in the message when you connect on the same machine.
"using password: YES" when you didn't type one
If the message says YES but you never typed a password, something sent one for you. The usual suspect is an old ~/.my.cnf file, which the client reads every time it starts. You can see what it'll use:
mysql --print-defaults
mysql would have been started with the following arguments:
--user=app --password=Old-pass-000
That stored password was changed months ago, so every connection fails with (using password: YES), even mysql -u app with no -p. Update the file, or delete the password line and type it with -p. The MYSQL_PWD environment variable, if it's set, does the same thing, so check echo $MYSQL_PWD too.
The other way a correct password arrives wrong is the shell itself. A password with $ in it, typed straight after -p, is changed by the shell before MySQL sees it:
mysql -u pay -pPa$$word-9 -e "SELECT 1"
ERROR 1045 (28000): Access denied for user 'pay'@'localhost' (using password: YES)
The shell replaced $$ with a number, its own process ID. Wrap the password in single quotes, -p'Pa$$word-9', or type just -p and enter it at the prompt, where the shell can't touch it.
MariaDB on Amazon Linux 2023: root has no password
Here's the first surprise. On a new MariaDB server on Amazon Linux 2023, root doesn't have a password you've forgotten; it has none at all:
sudo mysql -N -e "SHOW CREATE USER root@localhost"
CREATE USER `root`@`localhost` IDENTIFIED VIA mysql_native_password USING 'invalid' OR unix_socket
Read it from the end: unix_socket means "let in whoever is the Linux user root", and the password half is set to 'invalid', which no password can match. So sudo mysql works, and anything else is refused, with ERROR 1698 rather than 1045, password or not:
mysql -u root -p
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
That's a safe default, not a fault: nobody can guess a password that doesn't exist. For your app, and for tools that need a password, create a separate account instead of changing root.
Jake: "So root's password was never lost. There wasn't one?"
Ethan: "There wasn't one. The server trusted my sudo. Then I gave it a password and it stopped trusting my sudo."
The trap: a MySQL tutorial that locks sudo mysql out
Here's what Ethan ran, straight from a MySQL guide:
sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'Root-pass-1';"
sudo mysql -e "SELECT 1"
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
On MariaDB, IDENTIFIED BY replaces how root signs in. The unix_socket part is gone, so sudo no longer counts, and root now needs the password, which sudo mysql doesn't send. If you know the password you set, sign in with it and put both methods back, so sudo mysql works again and the password works too:
sudo mysql -u root -p'Root-pass-1' -e "ALTER USER 'root'@'localhost' IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('Root-pass-1');"
sudo mysql -N -e "SELECT CURRENT_USER()"
root@localhost
If you don't know it any more, the reset below works the same.
Reset a forgotten root password on your own server
To reset root, you restart the server in a mode that skips all password checks, set the password, and restart it normally. On Amazon Linux 2023, MariaDB's service reads extra options from MYSQLD_OPTS, so you don't edit any files:
- Stop the server, and start it without password checks and without network access, so nobody else can get in while it's open.
- Run
FLUSH PRIVILEGESfirst; it reloads the account tables, and without it everyALTER USERfails with ERROR 1290. - Set root back to how you want it: socket only, as below, or socket plus a password.
- Remove the extra options and restart normally.
sudo systemctl stop mariadb
sudo systemctl set-environment MYSQLD_OPTS="--skip-grant-tables --skip-networking"
sudo systemctl start mariadb
sudo mysql -e "FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED VIA unix_socket;"
sudo systemctl unset-environment MYSQLD_OPTS
sudo systemctl restart mariadb
sudo mysql -N -e "SELECT CURRENT_USER()"
root@localhost
Skip step 2's FLUSH PRIVILEGES, and the client repeats your statement back, then stops with this error:
ERROR 1290 (HY000) at line 1: The MariaDB server is running with the --skip-grant-tables option so it cannot execute this statement
Don't leave out --skip-networking on MariaDB. Without it, the server keeps accepting network connections while password checks are off, so anyone who can reach port 3306 gets in as anyone. MySQL 8.4 turns networking off by itself in this mode; MariaDB 10.11 doesn't:
| MariaDB 10.11 (Amazon Linux 2023) | MySQL 8.4 (Docker image) | |
|---|---|---|
| How root signs in by default | sudo mysql, by system identity | Password from MYSQL_ROOT_PASSWORD |
| Wrong root login gives | ERROR 1698 | ERROR 1045 |
Network off with --skip-grant-tables | No: add --skip-networking | Yes, automatically |
FLUSH PRIVILEGES before ALTER USER | Needed | Needed |
Jake: "Isn't that a back door?"
Ethan: "Only for someone who can already run sudo on the server. If they can do that, the database is the least of your worries."
MySQL in Docker: the password from the first start wins
The official MySQL image sets root's password from MYSQL_ROOT_PASSWORD, and leaving out -p gives the plain version of the error:
docker exec -it shop-mysql mysql -u root
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
Here's the second surprise. The image only uses MYSQL_ROOT_PASSWORD when it creates the database, on the very first start with an empty volume. Change the value in your docker-compose.yml later, recreate the container, and the new password fails with (using password: YES) while the old one still works, because the database in the volume kept it. You have three ways out:
- Use the old password, then change it properly with
ALTER USER. - Reset it, as below, keeping your data.
- If the data is disposable, a test database, remove the volume and let the image create a new one with the new password. This deletes everything in it.
To reset it, start a temporary container on the same volume in skip-grant mode, wait a few seconds for it to start, set both root accounts (the image creates root@localhost and root@%), then go back to your normal container:
docker stop shop-mysql
docker run --rm -d --name mysql-reset -v shop-data:/var/lib/mysql mysql:8.4 --skip-grant-tables
docker exec mysql-reset mysql -u root -e "FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY 'New-pass-3'; ALTER USER 'root'@'%' IDENTIFIED BY 'New-pass-3';"
docker stop mysql-reset
docker start shop-mysql
Update MYSQL_ROOT_PASSWORD in your compose file to match, so the next person isn't confused by it.
App accounts: wrong password, or the wrong account
For an app's account, (using password: YES) usually means just what it says. But there's one classic case where the password is right and MySQL compares it with a different account. An anonymous account, one with an empty user name, made for localhost, beats 'app'@'%' for connections from this machine, because MySQL picks the most specific host first:
sudo mysql -e "SELECT user, host FROM mysql.user WHERE user = '';"
User Host
localhost
A row like that means app on this machine is checked against the anonymous account, which has a different password, so it fails with 1045 every time. A fresh MariaDB on Amazon Linux 2023 has no anonymous accounts, but older installs and copied data sometimes do. Remove it, and the same login works:
sudo mysql -e "DROP USER ''@'localhost';"
If you inherited a server you didn't set up, also run sudo mariadb-secure-installation, which walks you through removing anonymous accounts and test databases.
RDS: reset the master password in one command
On RDS there's no --skip-grant-tables, and there doesn't need to be. Change the master password from outside the database:
aws rds modify-db-instance --db-instance-identifier shop-db --master-user-password 'New-Strong-Pass-4' --apply-immediately
This doesn't cause an outage; RDS applies the change in the background, as soon as it can. It also restores the master user's privileges if someone revoked them by accident, which makes it the way back in after a bad REVOKE, too. The password can use any printable ASCII character except /, " and @.
If the database stores its master password in AWS Secrets Manager, the command above is refused; read the current password from the secret instead:
aws rds describe-db-instances --db-instance-identifier shop-db --query "DBInstances[].MasterUserSecret.SecretArn" --output text
aws secretsmanager get-secret-value --secret-id <the ARN from above> --query SecretString --output text
A 1045 for a non-master RDS user is fixed the normal way: sign in as the master user and run ALTER USER.
Work through it in order
Most 1045 errors aren't a lost password, so resetting is the last step, not the first. Each check below takes seconds, and the first four solve the large majority of cases you'll run into. Start with the end of the message, because NO and YES send you down different paths, and check what the client actually sends before you change anything on the server:
- Read the ending:
NOmeans add-p;YESmeans the password sent was wrong. - Got 1698 for root on MariaDB? Use
sudo mysql. - Run
mysql --print-defaultsandecho $MYSQL_PWDfor a stored password. - Put passwords that contain
$in single quotes, or type them at the prompt. - Docker: try the password from the first start.
- Look for anonymous accounts with
user = ''. - Still locked out: reset with
--skip-grant-tables, or on RDS with--master-user-password.
Troubleshooting by symptom
sudo mysql gives ERROR 1045 (using password: NO)
Someone ran ALTER USER root IDENTIFIED BY on MariaDB, removing socket login. Sign in with the password, or reset it.
ERROR 1698 Access denied for user root@localhost
MariaDB's root signs in by system identity. Use sudo mysql, not mysql -u root -p.
New MYSQL_ROOT_PASSWORD doesn't work in Docker
The volume kept the password from the first start. Use the old one, or reset it.
using password: YES but I typed no password
A ~/.my.cnf file or the MYSQL_PWD variable sent one. Check mysql --print-defaults.
ERROR 1290 during the password reset
Run FLUSH PRIVILEGES first; in skip-grant mode, ALTER USER fails until you do.
Correct password, still 1045 from localhost
An anonymous ''@'localhost' account is being matched instead. Drop it.
MySQL ERROR 1045: frequently asked questions
What does ERROR 1045 Access denied for user root@localhost mean?
MySQL found an account that could match you, but the user name and password didn't match it.
What does (using password: NO) mean?
No password was sent. Add -p, or check whether the account needs one.
What does (using password: YES) mean?
A password was sent and it was wrong, or it was compared with a different account.
What is the MariaDB root password on Amazon Linux 2023?
There isn't one. Root signs in by system identity: run sudo mysql.
What is the difference between ERROR 1045 and ERROR 1698?
1045 is a password mismatch. 1698 is MariaDB refusing a socket-identity account, such as root, for the wrong Linux user.
Why does sudo mysql stop working after setting a root password?
On MariaDB, ALTER USER ... IDENTIFIED BY replaces socket login. Use IDENTIFIED VIA unix_socket OR mysql_native_password to keep both.
How do I reset the MySQL root password?
Restart with --skip-grant-tables (and --skip-networking on MariaDB), run FLUSH PRIVILEGES, then ALTER USER, then restart normally.
Why does ALTER USER fail with ERROR 1290?
The server is in skip-grant mode. Run FLUSH PRIVILEGES first.
Does --skip-grant-tables disable networking?
On MySQL 8.4, yes. On MariaDB 10.11, no: add --skip-networking yourself.
Why doesn't my new MYSQL_ROOT_PASSWORD work in Docker?
It only applies when the volume is empty. An existing database keeps its first password.
How do I reset the root password of MySQL in Docker?
Start a temporary container on the same volume with --skip-grant-tables, run FLUSH PRIVILEGES and ALTER USER for both root accounts.
How do I reset the RDS master password?
Run aws rds modify-db-instance with --master-user-password and --apply-immediately. It causes no outage.
My RDS master password is in Secrets Manager. How do I get it?
Get the secret ARN from describe-db-instances (MasterUserSecret), then read it with get-secret-value.
Why does a password with $ fail on the command line?
The shell changes it first. Put the password in single quotes, or type it at the prompt.
Where does mysql read a saved password from?
From option files such as ~/.my.cnf, and from MYSQL_PWD. mysql --print-defaults shows what it'll use.
What is an anonymous MySQL user?
An account with an empty user name. One for localhost can be matched before 'app'@'%' and cause 1045.
Why does the error say localhost when my user is 'app'@'%'?
The message shows where you connected from, not the host part of the account.
Ethan still knew the password he'd set, so he signed in with it and ran the IDENTIFIED VIA unix_socket OR mysql_native_password line, and sudo mysql worked again. Then he created a separate booking account for the app and stopped touching root altogether. Jake's verdict: "So you locked the front door with a key you didn't need, and the spare key was in your pocket the whole time." Ethan said that was about the size of it.
📌 If you keep one line from this page
Read the ending first: NO means no password was sent, YES means the wrong one was. On Amazon Linux 2023's MariaDB, root signs in with sudo mysql and has no password.
sudo mysql · mysql --print-defaults · FLUSH PRIVILEGES before ALTER USER · MYSQL_ROOT_PASSWORD = first start only · --master-user-password on RDS.
Revision note. Written October 14, 2026, for MariaDB 10.11 on Amazon Linux 2023, MySQL 8.4 and Amazon RDS. "If it ain't broke, don't fix it," as the saying goes; root's missing password was never broken.