You've just deployed your app, or moved a WordPress site, and instead of a homepage you get ERROR 1045 (28000): Access denied for user 'x'@'localhost' (using password: YES). It's one of the most common MySQL and MariaDB errors we see in support tickets, and it almost always comes down to one of five causes. Let's work through them in the order that saves you the most time.

What error 1045 actually means

MySQL checks three things when you connect: the username, the host you're connecting from, and the password. If any one of them doesn't match a row in its grant tables, you get 1045. The server deliberately doesn't say which part failed, so you have to check each one.

Note the two flavours of the message:

  • using password: YES means a password was sent, but it's wrong or the account doesn't exist for that host.
  • using password: NO means your app sent no password at all. That's usually an empty value in a config file or an environment variable that didn't load.

Symptom, cause, fix at a glance

SymptomLikely causeFix
Fails right after a migrationOld DB name, user or password in configUpdate wp-config.php or .env
Works in phpMyAdmin, fails in the appTypo, trailing space or special character in passwordReset the password and re-paste it
Works locally, fails from another serverUser only allowed from localhostAdd the remote host (cPanel) or create a user for that host (VPS)
using password: NOEmpty password in configCheck the config value or environment variable
Fails only as root on a VPSRoot uses socket authenticationUse sudo mysql instead

Fix 1: Check the credentials in your config

Start with the boring stuff. On WordPress, open wp-config.php and look at these four lines:

define( 'DB_NAME', 'cpuser_wp123' );
define( 'DB_USER', 'cpuser_wpuser' );
define( 'DB_PASSWORD', 'your-password-here' );
define( 'DB_HOST', 'localhost' );

On cPanel, database names and users are always prefixed with your account username, such as cpuser_wp123. If you migrated from another host and kept the old unprefixed name, that's your problem. For Laravel or Node apps, check .env and make sure there's no stray space or quote around the value.

Fix 2: Confirm the user is attached to the database (cPanel)

Here's a trap that catches a lot of people. Creating a database and creating a user in cPanel are two separate actions. The user has to be added to the database with privileges.

  1. Log in to cPanel and open MySQL Databases.
  2. Scroll to Add User To Database.
  3. Pick the user and the database, click Add, then tick All Privileges.

While you're there, use Change Password on the user and set a fresh password. Stick to letters and numbers if you're unsure how your app handles symbols. Then paste that same password into your config.

Fix 3: Passwords with special characters

Characters like $, #, &, @, quotes and backslashes can get mangled by shells, .env parsers and connection URLs. If your connection string looks like mysql://user:p@ss@localhost/db, the second @ breaks it. Either URL-encode the password (@ becomes %40) or pick a strong password without symbols. A 20-character alphanumeric password is perfectly safe.

To test from SSH without any app in the way:

mysql -u cpuser_wpuser -p -h localhost cpuser_wp123

Type the password at the prompt. If that works, MySQL is fine and the problem is in how your app reads the password.

Fix 4: The host part of the account (VPS)

On a VPS, MySQL accounts are tied to a host. 'app'@'localhost' and 'app'@'%' are two different accounts. If your app runs on a different server, a user created only for localhost will be rejected.

Log in as an admin and look:

sudo mysql
SELECT user, host, plugin FROM mysql.user;

Then create or fix the account for the right host:

CREATE USER 'app'@'203.0.113.10' IDENTIFIED BY 'StrongPassword123';
GRANT ALL PRIVILEGES ON appdb.* TO 'app'@'203.0.113.10';
FLUSH PRIVILEGES;

Replace the IP with your app server's address. Avoid '%' unless you've also restricted port 3306 in your firewall. Also check that bind-address in /etc/mysql/mysql.conf.d/mysqld.cnf (or /etc/my.cnf) isn't pinned to 127.0.0.1 if you need remote access. On cPanel hosting, remote hosts are whitelisted under Remote MySQL.

Fix 5: Root login fails on a fresh VPS

On recent Ubuntu, Debian and MariaDB installs, root authenticates through the Unix socket rather than a password. So mysql -u root -p fails with 1045 even though your password is right. Use this instead:

sudo mysql

That works because you're already root at the OS level. Don't switch root to a password just to make an app connect. Create a dedicated user per application with access to one database only. If you've genuinely lost the root password, we have a separate guide for resetting it.

Fix 6: Authentication plugin mismatch

If the credentials are right but an older PHP or client library still gets rejected, the account may use an authentication plugin that the client doesn't support. Check the plugin column from the query above. If it's caching_sha2_password and your old client can't use it, either upgrade the client library or switch that one user:

ALTER USER 'app'@'localhost' IDENTIFIED WITH mysql_native_password BY 'StrongPassword123';
FLUSH PRIVILEGES;

Prevention

  • Keep database credentials in one place (wp-config.php or .env) and note them in your password manager the moment you create them.
  • After any migration, test the connection from the command line before you change DNS.
  • Use one MySQL user per site, never root and never a shared user.
  • Prefer alphanumeric passwords, or URL-encode them if they go inside a connection string.
  • Take a backup before running ALTER USER or GRANT statements on a production server.

Frequently Asked Questions

Why does phpMyAdmin work but my website shows error 1045?

phpMyAdmin in cPanel logs in with your cPanel session, not your database user. So it proves nothing about the DB user's password. Test the database user from SSH or reset its password in MySQL Databases and update your config.

Is "Access denied" the same as "Error establishing a database connection"?

Often, yes. WordPress shows that generic message when MySQL rejects the login, and error 1045 is the underlying reason. Enabling WP_DEBUG or testing from the command line will show you the real MySQL message.

Do I need to restart MySQL after changing a password or grants?

No. ALTER USER and GRANT take effect immediately. Running FLUSH PRIVILEGES is only needed if you edited the grant tables directly.

Is it safe to use '%' as the host?

Only if port 3306 is protected by a firewall that allows your trusted IPs alone. A better habit is to grant access to the exact IP address of the server that needs it.