MySQL error 1045
ERROR 1045 (28000): Access denied for user
The server didn’t accept the user, password and client address you connected with. MySQL gives the same message for a wrong password, an unknown user and an account that only exists for another host.
ERROR 1045 (28000): Access denied for user 'seo_mysql_app'@'127.0.0.1' (using password: YES)
Tested on MySQL 8.4.11 and MariaDB 11.4.13 · Updated 9 October 2026
What it means
An account in MySQL and MariaDB is a user and a host: 'app'@'%' and 'app'@'localhost' are two
different accounts, each with its own password. When you connect, the server takes the most specific
account whose host matches the address it sees you coming from, and checks your password against that
one account. Error 1045 means the check failed.
The message is the same whether the password is wrong, the user doesn’t exist, or the user exists only for some other host. Two parts of it tell you more:
'app'@'127.0.0.1'is the user name you sent and the address the server saw. It isn’t necessarily an account that exists.(using password: NO)means your client sent no password at all. The password never reached the client: an empty environment variable, a missing-p, a config file that wasn’t read.
Common causes
- The password is wrong: a typo, an old password, or one read from a file or environment variable with a trailing newline or space.
- No password was sent (
using password: NO). - The account is for a different host.
'app'@'localhost'doesn’t match a TCP connection from another machine, and from your Mac to a server in Docker the server sees the Docker network’s gateway address (it was192.168.148.1here), notlocalhost. - A more specific account matches first. With both
'app'@'%'and'app'@'10.0.0.5', a connection from 10.0.0.5 is checked only against the second one and its password. - The user doesn’t exist on this server: a different server, port or container than you think, or a Docker volume that kept an older database.
- Special characters in a connection URL that weren’t percent-encoded, so the client sent a different password from the one you typed.
How to fix it
See which accounts exist for that user
Connect as an administrator and list every host the user has:
SELECT user, host, plugin FROM mysql.user WHERE user = 'app' ORDER BY host;
Compare the host column with the address in the error. % matches any address. With
skip_name_resolve on (the official MySQL and MariaDB Docker images turn it on), localhost matches
only connections through the Unix socket; a TCP connection to 127.0.0.1 is checked against a
127.0.0.1 or % account instead.
Once you can sign in, this shows who you asked to be and which account the server actually used:
SELECT USER(), CURRENT_USER();
Reset the password
Name the exact user and host from the list above:
ALTER USER 'app'@'%' IDENTIFIED BY '<new password>';
If the user has several hosts, each has its own password. Set the one you connect through.
Add an account for the address you connect from
If the user exists only for localhost and you connect over TCP (from another machine, or from your
Mac into Docker), create one for that address, or for %:
CREATE USER 'app'@'%' IDENTIFIED BY '<password>';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app'@'%';
Before you do, check for a more specific account that would still win for your address, and drop it if it’s stale.
Make sure a password is sent
With the mysql client, -p alone makes it ask; -p<password> takes no space. If the password
comes from an environment variable or a .env file, check it isn’t empty and has no newline at the
end. mysql --no-defaults ignores option files such as ~/.my.cnf, which can hold an old password.
Docker: the first start sets the password
The official MySQL and MariaDB images read MYSQL_ROOT_PASSWORD (or MARIADB_ROOT_PASSWORD),
MYSQL_USER and the rest only when the data directory is empty. If the volume already has a
database, changing those variables does nothing and the old passwords still apply. Sign in with the
old one and run ALTER USER, or remove the volume if its data is disposable.
Encode special characters in URLs
In a mysql:// URL, @, :, /, ?, # and % in the password must be percent-encoded:
p@ss:word becomes p%40ss%3Aword. See
special characters in passwords.
Error 1698 instead: socket authentication
An account that uses MariaDB’s unix_socket plugin (or MySQL’s auth_socket) checks your
operating-system user, not a password. MariaDB 10.4 and later create root@localhost that way, so
mysql -u root as a different OS user fails with a different number:
ERROR 1698 (28000): Access denied for user 'seo_mysql_sock'@'localhost'
Run the client as the matching OS user (sudo mariadb for root), or give the account a password.
Reproduce it
On MySQL 8.4.11, with an account 'seo_mysql_app'@'%', from the mysql client in the server’s
container:
mysql -h127.0.0.1 -useo_mysql_app -pwrong -e 'select 1'
ERROR 1045 (28000): Access denied for user 'seo_mysql_app'@'127.0.0.1' (using password: YES)
A user that doesn’t exist gets the same message, and leaving out -p changes only the end:
ERROR 1045 (28000): Access denied for user 'nobody'@'127.0.0.1' (using password: YES)
ERROR 1045 (28000): Access denied for user 'seo_mysql_app'@'127.0.0.1' (using password: NO)
An account 'seo_mysql_local'@'localhost' with the right password, over TCP:
ERROR 1045 (28000): Access denied for user 'seo_mysql_local'@'127.0.0.1' (using password: YES)
The same account through the socket (-hlocalhost) signs in. Then, after adding
'seo_mysql_app'@'127.0.0.1' with a different password, the % account’s password stopped working
from 127.0.0.1 with the same 1045, and the new one worked:
select user(), current_user();
user() current_user()
seo_mysql_app@127.0.0.1 seo_mysql_app@127.0.0.1
MariaDB 11.4.13 gave the same messages, number and SQLSTATE in every case. It also writes each
refusal to its error log, which MySQL 8.4 didn’t at its default log_error_verbosity of 2:
[Warning] Access denied for user 'seo_mysql_app'@'127.0.0.1' (using password: YES)
In Inlet
When the server refuses the password, the connection window shows the server’s message and asks for
the password right there; once the server accepts it, Inlet can save it in the Keychain. You can
also paste a mysql:// URL and Inlet fills in the form, so you can check the user, host and port
before you connect.
Related
- ERROR 2003 (HY000): Can't connect to MySQL server on 'host'
- ERROR 2002 (HY000): Can't connect to local MySQL server through socket
- ERROR 1049 (42000): Unknown database
- MySQL connection string: mysql:// URLs, mysql flags and option files
- Special characters in database passwords: percent-encoding connection URLs