How to fix "Error establishing a database connection" in WordPress on your own server

WordPress shows the same message for very different problems: the database is stopped, the password is wrong, or too many visitors are connected. This guide shows how to find out which one it is, in a few commands.

We tested every case in this guide on Debian 13 with WordPress 7.1, MariaDB 11.8, Nginx and PHP 8.4. We broke a working site on purpose, one way at a time, and copied the real messages. Ubuntu and MySQL work the same way.

What the message means

WordPress keeps your posts, users and settings in a database. On every page load, it logs in to the database with the name, user and password in wp-config.php. If that fails for any reason, you get "Error establishing a database connection" with HTTP status 500, on the site and in /wp-admin.

In our tests, these all gave exactly the same page:

  • MariaDB was stopped.
  • The password in wp-config.php was wrong.
  • The database name was wrong.
  • The database user had lost its rights.
  • All database connections were in use.

And none of them wrote anything to the Nginx or PHP logs. So you need to ask the database yourself.

1. Is the database running?

sudo systemctl status mariadb

On MySQL, use mysql instead of mariadb. If it says inactive or failed, start it:

sudo systemctl start mariadb

If it won't start, its log says why:

sudo journalctl -u mariadb -n 50

Two common reasons a database stops on a small server:

  • The server ran out of memory, and Linux killed the biggest program, which is often the database. Check with sudo journalctl -k | grep -i "killed process". Debian's MariaDB service restarts it 5 seconds after it's killed (Restart=on-abnormal in its service file), so the site may come back by itself and go down again later. See our guide to out-of-memory errors and swap.
  • The disk is full. Check with df -h. If / is at 100%, see stop logs filling the disk for how to find what's using the space.

2. Test the login from wp-config.php

If the database runs, check that WordPress's login works. First look at the settings (this doesn't print the password):

sudo grep -E "DB_(NAME|USER|HOST)" /var/www/example.com/wp-config.php

Then log in with the same user and database, exactly like WordPress does. Type the password from wp-config.php when asked (typing it at the prompt keeps it out of your shell history):

mysql -u wpuser -p -h localhost wordpress -e "SELECT 1"

Change wpuser, localhost and wordpress to your DB_USER, DB_HOST and DB_NAME. What we saw:

  • It prints 1: the login works. Go to step 3.
  • ERROR 1045 (28000): Access denied for user 'wpuser'@'localhost' (using password: YES): the password is wrong. Fix it in wp-config.php, or set a new one in the database (below).
  • ERROR 2002 (HY000): Can't connect to local server through socket '/run/mysqld/mysqld.sock': the database isn't running. Go back to step 1.
  • ERROR 1040 (08004): Too many connections: see step 4.
  • Any other "Access denied" or "Unknown database" error: the database name is wrong, or the user isn't allowed to use that database.

To set a new password or give the rights back, log in as the database admin. On Debian and Ubuntu, sudo mysql works without a password:

sudo mysql
SHOW DATABASES;
ALTER USER 'wpuser'@'localhost' IDENTIFIED BY 'a-new-long-password';
GRANT ALL ON wordpress.* TO 'wpuser'@'localhost';

Then put the same password in wp-config.php. In our test, giving the rights back fixed the site at once.

localhost or 127.0.0.1? On a normal Debian server both work. In our test, MariaDB saw both as wpuser@localhost. localhost uses a local socket file and is a little faster, so keep it unless your host told you otherwise.

3. The login works, but WordPress still fails

If SELECT 1 works with the same details, WordPress probably isn't reading what you think:

  • Wrong file. Make sure you changed the wp-config.php of the site that's broken. On a server with several sites, check the root line in the site's Nginx file.
  • The change isn't picked up yet. PHP's OPcache keeps a copy of wp-config.php. In our test, a changed password took effect only after about 2 seconds. If your server has opcache.validate_timestamps = 0 (see our OPcache guide), PHP never notices the change. Reload PHP-FPM: sudo systemctl reload php8.4-fpm.
  • A typo with quotes. A password with a ' or \ in it can break the line. Check that PHP can read the file: sudo php -l /var/www/example.com/wp-config.php.

4. "Too many connections"

Each visitor's page needs a database connection for a short time. When all connections are in use, new visitors get the error until one is free. In our test, we set the limit low and held all connections open: the site showed the error, and it came back by itself when they were done.

The admin can still log in when everyone else is turned away, so you can see who's connected:

sudo mysql -e "SHOW PROCESSLIST"
sudo mysql -e "SHOW GLOBAL STATUS LIKE 'Max_used_connections'; SHOW VARIABLES LIKE 'max_connections'"

Look for many queries in the same state, or one that runs for a long time. Usually the real problem is slow queries that hold connections too long, or a bot hitting the site. Raising the limit alone often just moves the problem to memory. These help more:

See the real error, without showing it to visitors

WordPress can tell you the exact reason. But don't turn on WP_DEBUG alone: in our test, it showed the full error, with the database user name, on the public page. Write it to a log file instead, outside the website's folder:

sudo mkdir -p /var/log/wordpress
sudo chown www-data: /var/log/wordpress

Then, in wp-config.php, above the line /* That's all, stop editing! */:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/var/log/wordpress/debug.log' );
define( 'WP_DEBUG_DISPLAY', false );

In our test, visitors saw only the normal error page, and the log had the reason: mysqli_real_connect(): (HY000/1045): Access denied for user 'wpuser'@'localhost'. With WP_DEBUG_LOG set to true, WordPress writes to wp-content/debug.log instead, and in our test anyone could download that file. Use a path outside the website, and turn WP_DEBUG off again when you're done. If the site runs in its own PHP-FPM pool, give the folder to that pool's user instead of www-data.

After it works again

Quick list

  • Database stopped: systemctl start mariadb, then check memory (journalctl -k | grep -i killed) and disk (df -h).
  • Access denied (1045): the password in wp-config.php doesn't match. Fix it, or set a new one with ALTER USER.
  • Other access errors: wrong database name, or the user lost its rights (GRANT ALL ON ...).
  • Login works from the terminal but not in WordPress: wrong file, OPcache, or a quote in the password.
  • Too many connections (1040): look at SHOW PROCESSLIST, then fix slow queries or bots.
  • Need the exact reason: turn on WP_DEBUG_LOG with a path outside the website, never WP_DEBUG on its own.

Official sources

Next steps: run through the WordPress hardening guide, and see fixing 502 and 504 errors if Nginx shows those instead.

ServerNest is being built to check that each site's database is up and reachable, and to tell you when it isn't. Join early access to try it first.

← Back to the security blog