1045 🐬 MySQL MySQL 5.7+, MariaDB

MySQL ERROR 1045 (28000): Access denied for user

MySQL rejected the login — wrong password, wrong user/host combination, or the user doesn’t exist.

Seen on: MySQL Linux PHP Docker

Meaning

MySQL accounts are user@host pairs. 'app'@'localhost' and 'app'@'%' are different accounts with possibly different passwords. The message tells you which host MySQL matched and whether a password was sent (“using password: YES/NO”).

Common causes

  • Wrong password (or special characters mangled by the shell/config)
  • User exists for a different host (localhost vs 127.0.0.1 vs %)
  • “using password: NO” — the app didn’t send any password (empty env var)
  • Root uses auth_socket on Ubuntu, so password login fails
  • Docker: connecting to localhost instead of the DB container hostname
  • User was created but privileges not granted on the database

⚡ Quick fix

  1. Check “using password: YES/NO” — NO means your config is empty
  2. Log in as root and list accounts: SELECT user, host, plugin FROM mysql.user;
  3. Create/alter the user for the exact host the app connects from
  4. Grant privileges on the database
  5. In Docker, use the service name as host (e.g. db)

Detailed fix by platform

MySQL

  1. Create or fix the user (MySQL 8 / MariaDB):
    sql
    CREATE USER IF NOT EXISTS 'app'@'localhost' IDENTIFIED BY 'StrongPass!23';
    ALTER USER 'app'@'localhost' IDENTIFIED BY 'StrongPass!23';
    GRANT ALL PRIVILEGES ON appdb.* TO 'app'@'localhost';
    FLUSH PRIVILEGES;

Linux

  1. Ubuntu root via socket: sudo mysql works without a password; use it to create a separate app user instead of using root.

PHP

  1. Check the DSN host and that .env values are loaded (Laravel: php artisan config:clear after editing .env).

Docker

  1. Use MYSQL_USER/MYSQL_PASSWORD env vars on first start only — changing them later doesn’t update an existing data volume.

Code examples

Test exactly what the app uses

bash
mysql -h 127.0.0.1 -P 3306 -u app -p appdb

-h localhost uses the Unix socket; -h 127.0.0.1 uses TCP — they can match different accounts.

How to diagnose

  1. Message — Which user@host, and password YES or NO?
  2. Accounts — Does that exact user@host exist?
  3. Password — Correct and not mangled by quoting?
  4. Privileges — Granted on the target database?
  5. Network — Right host (socket vs TCP vs container name)?

🧠 Still stuck? Analyze your error

Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.