# MySQL ERROR 1045 (28000): Access denied for user

**Code:** `1045` · **Category:** MySQL · **Seen on:** MySQL, Linux, PHP, Docker

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

## 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)?

---
Source: [WhatIsMyError](https://whatismyerror.com/errors/mysql/1045-access-denied)
