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.
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.phpwas 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-abnormalin 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 inwp-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.phpof the site that's broken. On a server with several sites, check therootline 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 hasopcache.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:
- Find and fix slow queries: finding slow database queries.
- Slow down bots: rate limiting with Nginx.
- Too many PHP workers for your memory can also mean too many connections. See our PHP-FPM guide for the right number.
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
- Make sure you have a recent backup of the database, and that you've tested it. See back up a PHP website and test the restore.
- Get told next time. An outside check notices within minutes. See simple uptime monitoring.
- Keep the database safe: see MySQL and MariaDB security.
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.phpdoesn't match. Fix it, or set a new one withALTER 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_LOGwith a path outside the website, neverWP_DEBUGon its own.
Official sources
- Debugging in WordPress (WordPress.org) (
WP_DEBUG,WP_DEBUG_LOG,WP_DEBUG_DISPLAY) - Editing wp-config.php (WordPress.org)
- MariaDB: max_connections and ALTER USER
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.