MySQL error 1045 (Access denied), explained and fixed

ERROR 1045 (28000): Access denied for user 'app'@'localhost' (using password: YES) is MySQL's authentication rejection. The server was reached and understood the request; the credentials or the account itself failed. The subtlety that makes this error confusing is in the address part: MySQL accounts are a user and a host pattern together, so 'app'@'localhost' and 'app'@'%' are different accounts with potentially different passwords, and the server picks the most specific match for where the connection actually came from.

Work through it in order

  1. Verify the credentials exactly: retype rather than paste when testing, check for a rotated password, an environment variable the application reads that differs from the one you are testing with, and trailing whitespace in configuration values.
  2. Check which account MySQL thinks you are: the 'user'@'host' in the message is the account the server matched, and it may not be the one whose password you set. A connection over the local socket matches localhost entries; the same client over TCP to 127.0.0.1 matches the TCP host rules instead, which is why “the same login” can pass one way and fail the other.
  3. Inspect the accounts (as an admin): SELECT user, host FROM mysql.user WHERE user = 'app'; lists the real combinations. If the combination your client matches does not exist, create it or grant appropriately; if it exists, reset that specific account's password: ALTER USER 'app'@'localhost' IDENTIFIED BY '...';.
  4. Watch for anonymous accounts: a leftover anonymous user entry (''@'localhost') can capture local connections and shadow the intended account during matching; removing unused anonymous accounts is standard hardening and a real fix for some 1045s.

Reading the message's details

  1. “(using password: YES)” means a password was sent and rejected (or matched no account). “NO” means the client sent none, check the client configuration rather than the server.
  2. The SQLSTATE is 28000 and client libraries surface it as error 1045; applications logging only “access denied” should be made to log the full server message, the user@host half is the diagnostic.

Common questions

Root itself gets 1045 and no admin login works, what then? MySQL documents a recovery procedure: start the server with --skip-grant-tables (ideally with networking restricted), connect locally, reload the grant tables with FLUSH PRIVILEGES, and set a new root password with ALTER USER, then restart normally. It requires shell access to the server host and is a break-glass procedure, not a routine step.

Why did it break when the app moved to a container? The connection's apparent origin changed (the container's network identity, or socket versus TCP), so MySQL now matches a different user@host account, or none. The credentials did not change; the matching did.

Is 1045 a security risk or an attack? By itself it is a failed login. A flood of them in the server log from external addresses is password guessing and worth addressing at the network layer, but a single 1045 from your own application is configuration, not intrusion.

Related errors

MySQL error 2002 (cannot connect) · PostgreSQL: password authentication failed · ORA-01017: invalid username/password