The front of your site shows a plain white page with one sentence: Error establishing a database connection. The dashboard is unreachable. Forms, checkouts and logins all fail the same way, because WordPress cannot talk to MySQL or MariaDB at all. In most cases you can pinpoint the cause and fix it within 15 minutes without touching the database itself.
What this error actually means
WordPress stores posts, users, settings and order data in a database, and loads that data through the $wpdb class on every request. When PHP cannot open a connection to the database, or the database closes the connection mid-handshake, WordPress has no data to render. It halts and prints this error instead of a page. The cause is almost always on the database side, not in PHP or the theme.
Common causes, ordered by likelihood
- Wrong credentials in
wp-config.php. The most common cause by a wide margin. Usually happens after a migration, a password rotation, or a host that silently moved your database to a different server. - Database server down or unreachable. A host-side outage, a crashed MySQL process on a VPS, or a network issue between the web server and the database server.
Too many connectionsfrom max_connections being hit. Traffic spike, runaway plugin, or a backup job holding sessions open. MySQL documents this as a hard limit on concurrent clients, typically 151 by default.- Database user permissions revoked or user deleted. Happens when a control panel rebuilds users after a billing change, or when someone manually cleans up an old user.
- Corrupted tables. Rare with InnoDB, more common with legacy MyISAM tables or after a forced server reboot during a write.
Diagnose before you fix
Before you change anything, confirm which of the five causes you are looking at. This takes two minutes and stops you from editing wp-config.php for a problem that lives on the database server.
Create a small file called dbcheck.php in your WordPress root with only this content:
<?php
// Read the same constants WordPress uses, so this matches wp-config.php exactly.
require __DIR__ . '/wp-config.php';
$link = @mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if (!$link) {
echo 'FAIL: ' . mysqli_connect_errno() . ' ' . mysqli_connect_error();
exit;
}
echo 'OK: connected to ' . DB_NAME . ' on ' . DB_HOST;
mysqli_close($link);
Open it in your browser at https://yoursite.nl/dbcheck.php and read the exact error number and message. Delete this file the moment you have your answer, because it exposes your database host. The MySQL error reference maps the number to a root cause:
1045 Access deniedpoints at wrong user or password1044 Access denied for user to databasepoints at permissions on the database itself1049 Unknown databasepoints at a wrongDB_NAME2002 Can't connect to MySQL serveror2005 Unknown MySQL server hostpoints atDB_HOSTor a dead database server1040 Too many connectionsmeansmax_connectionsis saturated
You now know which fix below to jump to.
Fix 1: wrong credentials in wp-config.php
This is where you start if dbcheck.php returned 1044, 1045 or 1049, or if the site went down right after a migration, a password change or a host move.
Open wp-config.php in the WordPress root over SFTP or the host's file manager. You are looking for four constants:
define('DB_NAME', 'mysite_wp');
define('DB_USER', 'mysite_wp');
define('DB_PASSWORD', 'correct-horse-battery-staple');
define('DB_HOST', 'localhost');
Compare each value against your hosting panel's database section. Passwords are case sensitive and special characters are a frequent culprit, especially when a control panel auto-generated one with ' or $ in it. For DB_HOST (see the wp-config.php settings reference for the full database-constant table), shared hosting is almost always localhost, but managed and cloud hosts often use a hostname like db-primary.internal or a socket path such as localhost:/var/run/mysqld/mysqld.sock. When in doubt, the correct value is whatever the hosting panel shows next to the database, not what you remember from the old server.
Save the file, reload the front page, and re-run dbcheck.php. You know it worked when the front page renders normally and dbcheck.php prints OK: connected.
Fix 2: database server is down or unreachable
You land here when dbcheck.php returned 2002 or 2005, or when the credentials look correct but the connection simply times out.
Check the host's status page first. Good hosts post outages proactively; seeing a current incident for "MySQL cluster" or "database server 04" is the fastest answer you will get. If the host is silent, log in to the hosting panel and try to open phpMyAdmin or Adminer. If phpMyAdmin also refuses to connect, the database server itself is down and there is nothing to fix on your side. Open a ticket with the exact error and the database host name.
If you run your own VPS or cloud server, SSH in and check the service:
# systemd on Debian/Ubuntu with MariaDB 10.6
systemctl status mariadb
# or MySQL 8.0
systemctl status mysql
If the service is inactive or failed, check disk space first with df -h. A full disk is the single most common reason MySQL refuses to start or dies mid-request. Once you have free space, start the service again and tail the log:
tail -n 50 /var/log/mysql/error.log
You know it worked when systemctl status shows active (running) and dbcheck.php returns OK: connected.
If the site comes back but goes down again within minutes, you are probably hitting a deeper resource problem. The article on high CPU usage on a WordPress server walks through finding the process that is eating the box.
Fix 3: Too many connections (max_connections hit)
dbcheck.php returns 1040 when the database has exhausted its connection pool. The MySQL documentation describes max_connections as the limit MySQL enforces on concurrent clients, with a default of 151 on MySQL 8.0 and MariaDB 10.6.
On shared hosting you cannot raise the limit yourself. Contact your host with the 1040 error and the time it started, and ask whether a neighbor on the same database server is saturating the pool. On a VPS or managed server you control, log into MySQL as an admin and confirm:
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
SHOW PROCESSLIST;
If Threads_connected is close to max_connections, scan the process list for long-running queries. Nine times out of ten it is a backup job, a search query from an overbuilt plugin, or a crawler hitting a slow page repeatedly. Kill the worst offenders with KILL <id> to recover quickly, then address the root cause: add caching, limit concurrent backups, or raise max_connections in my.cnf only if you also have the RAM to back it up. Each connection costs memory, so doubling max_connections on a 2 GB VPS is a good way to trade one outage for another.
You know it worked when dbcheck.php returns OK and SHOW STATUS LIKE 'Threads_connected' sits well below the limit during a normal load test.
If this keeps happening, the underlying problem is usually a slow query pattern, not a hard limit. The article on a slow WordPress database covers how to find the query that is holding connections open.
Fix 4: database user permissions revoked
You land here when dbcheck.php shows 1044 (access to the database is refused even with correct username and password), or when the credentials in wp-config.php match the panel exactly but phpMyAdmin login with the same values also fails.
In cPanel and Plesk this usually means the user was detached from the database. Go to the database section, find your database, and re-attach the user with ALL PRIVILEGES (except GRANT OPTION, which WordPress never needs). If the user itself was deleted, create a new one, assign it to the database, and update DB_USER and DB_PASSWORD in wp-config.php. Save, reload, and check with dbcheck.php.
You know it worked when dbcheck.php returns OK: connected and the WordPress dashboard loads.
Fix 5: corrupted tables
Corruption is the last thing to check, because it is the least common cause on modern WordPress installs. You are here if dbcheck.php connects successfully but WordPress still shows the error intermittently, or if the dashboard shows a separate notice like One or more database tables are unavailable. The database may need to be repaired.
Before touching anything, make a full database export through your host's backup tool or phpMyAdmin's Export function. Then enable WordPress repair mode by adding one line to wp-config.php:
define('WP_ALLOW_REPAIR', true);
Visit https://yoursite.nl/wp-admin/maint/repair.php and run Repair Database. Remove the line the moment you are done. While it is set, the repair page is accessible without login, which is a serious exposure.
One important caveat: the repair page runs the MySQL REPAIR TABLE statement, which only works on MyISAM and Aria tables. InnoDB has been the default WordPress storage engine for years and does not support REPAIR TABLE. If your tables are InnoDB and the repair page does nothing useful, the correct recovery path is to dump the broken table, drop it, and re-import it from a backup. On a healthy server InnoDB's own crash recovery handles most problems automatically at startup, so corruption severe enough to survive a restart almost always means you need to restore from backup.
You know it worked when the dashboard notice disappears and the site loads normally for a full page-load test across front page, a product page, and a login.
When to escalate
If none of the five fixes above resolves the error, stop poking at the database and open a ticket with your host or with me. Before you do, collect the following so the first response can actually help you:
- The exact error string (front-end message and any admin-side notice)
- The exact error number from
dbcheck.php(for example1045or2002) - Your WordPress, PHP and MySQL or MariaDB versions
- Your hosting tier (shared, VPS, managed, cloud)
- The value of
DB_HOSTfromwp-config.php - Any change made to the site in the last 48 hours, including migrations, plugin updates, password rotations and backup jobs
- The last 50 lines of
/var/log/mysql/error.logor the equivalent in your hosting panel
This information is the difference between a support engineer guessing and a support engineer fixing it in one reply.
A database error that only shows up inside /wp-admin and not on the front page can also surface as the critical error on this website notice, because WordPress catches the fatal and hides the specific cause behind the generic message. If you are seeing both, treat the database error as the root cause. The same goes for transactional email that suddenly stops sending, because WordPress stores email queues and settings in the database and cannot send anything while the connection is down.
Prevent recurrence
- Automate daily database backups and test a restore once a quarter. A backup you have never restored is a hope, not a backup.
- Cache aggressively so traffic spikes do not reach the database in the first place. Page caching turns 100 requests into one query.
- Monitor database connection count and the 1040 error, not just uptime. A good monitor warns you at 70% of
max_connectionsso you can act before the site falls over. - On shared hosting, ask your host what their
max_connectionsis and whether they throttle noisy neighbors. If they cannot answer either question, that is a signal about the tier. - Rotate database passwords deliberately, with a short checklist that includes updating
wp-config.phpat the same time. Most "surprise" credential failures are self-inflicted and forgotten.