“Error establishing a database connection” means WordPress could not connect to its MySQL or MariaDB database, so it cannot build any page: posts, settings and users all live there. The usual causes are wrong credentials in wp-config.php (after a migration or password change), a stopped or overloaded database server, and exhausted hosting limits. Start with two actions: open /wp-admin/, where WordPress shows a more detailed message, and compare DB_NAME, DB_USER, DB_PASSWORD and DB_HOST with the database details in your hosting panel.
What the error means and how WordPress displays it
On every request WordPress connects to the database server and then selects its database. If either step fails, nothing else loads. Visitors see a short heading, sent with HTTP status 500 so search engines do not cache it.
The catch: the front end shows the same text for several different problems. The detailed messages appear in the admin area, so open https://example.com/wp-admin/ and match what you see against this table.
| Message | Where | Meaning | Next step |
|---|---|---|---|
| Error establishing a database connection | Any front-end page | Connecting or selecting the database failed, cause not shown | Open /wp-admin/ or enable WP_DEBUG temporarily |
| Same heading plus a hint about wrong credentials or host | /wp-admin/ | The server rejected the login or does not answer at DB_HOST | Check DB_USER, DB_PASSWORD, DB_HOST and whether MySQL runs |
| Cannot select database | /wp-admin/ | Credentials work, but the database does not exist or the user has no rights to it | Check DB_NAME, the name prefix and user privileges |
| One or more database tables are unavailable. The database may need to be repaired. | /wp-admin/ | Connected, but some tables are missing or damaged | Repair tables or restore a backup |
| Could not find site … Searched for table … | Multisite | Database is reachable, but the domain is not in the network tables | Check DOMAIN_CURRENT_SITE, wp_site and wp_blogs |
| WordPress installation screen | Any page | Empty database or $table_prefix does not match the tables | Fix $table_prefix, do not reinstall |
If the admin shows only the short heading too, briefly set define( ‘WP_DEBUG’, true ); and define( ‘WP_DEBUG_DISPLAY’, true ); in wp-config.php. The exact server response, such as Access denied for user ‘user_wp’@’localhost’, then appears above the message. Set both back to false afterwards. If WordPress instead shows “There has been a critical error on this website”, follow our guide to fixing the WordPress critical error.
Quick diagnosis in five steps
- Read the message in /wp-admin/. The table above narrows the search to one or two causes.
- Check other sites and phpMyAdmin. If everything is down, the database server is the problem.
- Compare wp-config.php with the panel. Name, user and host must match exactly, including the prefix.
- Log in to phpMyAdmin with the wp-config.php credentials. Login fails: wrong user or password. Login works but the database is not listed: the user has no rights to it.
- Check resources and logs. A full disk, exhausted inodes, out-of-memory restarts or Too many connections point to limits or a server failure.

7 causes and how to fix each one
1. Wrong credentials in wp-config.php
The classic case: a migration, a password change in the panel or an edited wp-config.php. The file sits in the site root:
define( 'DB_NAME', 'user_wp' );
define( 'DB_USER', 'user_wp' );
define( 'DB_PASSWORD', 'your-password' );
define( 'DB_HOST', 'localhost' );
$table_prefix = 'wp_';
- Many control panels automatically prefix database and user names with the account name and an underscore: create a database called wp and you get user_wp. After moving from another panel the prefix almost always differs.
- Stray spaces, curly quotes or a password cut short while copying.
- A single quote or backslash in the password must be escaped in a PHP string (\’ and \\). It is easier to set a new password made of letters, digits and hyphens.
The most reliable fix is to set a new database password in the hosting panel and put it into wp-config.php. Over SSH, WP-CLI does this without needing a working database connection:
cd /home/user/web/example.com/public_html
wp config get DB_NAME
wp config get DB_HOST
wp config set DB_PASSWORD 'new-password'
If the database moved together with the site, make sure the dump was fully imported. Common traps are covered in our guide to hosting migration without losses.
2. Wrong DB_HOST
On most shared hosting DB_HOST is localhost; some providers use a separate database server and show its address in the panel. Note that for PHP, localhost means a Unix socket, while 127.0.0.1 means TCP port 3306. If PHP cannot find the socket, switching to 127.0.0.1 often helps.
| DB_HOST value | How PHP connects | When to use |
|---|---|---|
| localhost | Unix socket from PHP settings | Default for shared hosting and VPS |
| 127.0.0.1 | TCP, port 3306 | Socket unavailable or MySQL accepts TCP only |
| 127.0.0.1:3307 | TCP, custom port | A second MySQL or MariaDB instance |
| localhost:/run/mysqld/mysqld.sock | Explicit socket path | Socket lives in a non-default location |
| db.example.net | TCP to a remote server | Your host gave you a separate database server |
3. The database is missing or the user has no privileges
Cannot select database means the login worked but DB_NAME is unavailable: missing, misspelled, or not assigned to the user. In many panels the user is created together with the database, so check in the databases section that DB_NAME and DB_USER belong to the same entry. On a VPS:
sudo mysql -e "SHOW DATABASES;"
sudo mysql -e "SHOW GRANTS FOR 'user_wp'@'localhost';"
sudo mysql -e "GRANT ALL PRIVILEGES ON user_wp.* TO 'user_wp'@'localhost';"
4. MySQL or MariaDB has stopped
If every site on the account is down and phpMyAdmin will not open, the database service is not running. On shared hosting, contact support. On a VPS, check the service and why it stopped:
sudo systemctl status mariadb # or mysql
sudo journalctl -u mariadb -n 50 --no-pager
sudo dmesg -T | grep -i -E "out of memory|killed process"
df -h # free disk space
df -i # free inodes
sudo systemctl restart mariadb
Typical scenarios: the OOM killer terminated mysqld, the disk is full, or a config error after an update prevents startup. A restart only helps in the first case, and only until the next peak, so find out what eats memory.
5. Hosting limits are exhausted
An error that comes and goes is usually about limits. The database server caps concurrent connections both globally (max_connections, 151 by default in MySQL and MariaDB) and per user (max_user_connections, set by the provider on shared hosting). Once a cap is reached, new requests get 1040 Too many connections or 1203 User already has more than ‘max_user_connections’ active connections, and visitors see the database error.
PHP processes hold the connections, so they run out for the same reasons CPU does: bots on wp-login.php and xmlrpc.php, heavy plugins, no page cache, busy wp-cron. These are also the usual signs of a slow WordPress site. On a VPS:
sudo mysql -e "SHOW VARIABLES LIKE 'max%connections';"
sudo mysql -e "SHOW GLOBAL STATUS LIKE 'Threads_connected';"
sudo mysql -e "SHOW GLOBAL STATUS LIKE 'Max_used_connections';"
sudo mysql -e "SHOW FULL PROCESSLIST;"
Do not raise max_connections blindly: every connection uses memory, so you may trade refused connections for a crashed server. Enable page caching, block xmlrpc.php, move wp-cron to system cron and check access logs for the source of load. If legitimate traffic keeps hitting the limits, the site has outgrown its plan.
6. Corrupted database tables
Hard shutdowns, a full disk or an interrupted import damage tables. Signs: One or more database tables are unavailable in the admin, or Table ‘wp_options’ is marked as crashed in logs. Back up first (wp db export or a phpMyAdmin export), then:
- Built-in repair tool. Add define( ‘WP_ALLOW_REPAIR’, true ); to wp-config.php and open https://example.com/wp-admin/maint/repair.php. The page works without logging in, so remove the line as soon as you finish.
- WP-CLI. wp db check checks the tables, wp db repair repairs them.
- phpMyAdmin. Select the tables and choose Repair table.
REPAIR TABLE works for MyISAM and Aria; modern WordPress tables are mostly InnoDB, which recovers on startup. If InnoDB will not start, innodb_force_recovery is used only to dump data: values of 4 and higher can permanently corrupt files. Without experience, restore a recent backup instead (see our notes on backup management).
7. A db.php drop-in, damaged files or a hack
If the credentials are right and phpMyAdmin works, look in wp-content. A db.php file there is a drop-in that replaces the database class; query caching plugins and multi-server tools such as HyperDB or LudicrousDB create it and read their own config instead of wp-config.php. Rename db.php to db.php.off: if the site comes back, the plugin that created it is the cause.
After a failed update, upload fresh wp-admin and wp-includes folders from wordpress.org, leaving wp-content and wp-config.php alone. If wp-config.php contains lines you did not add, treat it as a compromise: change the database, FTP and admin passwords, scan the files and review your hosting security. For wp-config.php, permissions 640 or 600 are usually enough when PHP runs as the file owner, as it usually does on shared hosting.
Test script: check the connection without WordPress
This script uses the same credentials as WordPress and prints the exact MySQL error. Save it in the site root under a random name such as db-check-7f3a.php, fill in your values and open it in a browser.
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$link = @mysqli_connect('localhost', 'user_wp', 'your-password', 'user_wp');
if (!$link) {
exit('ERROR ' . mysqli_connect_errno() . ': ' . mysqli_connect_error());
}
echo 'OK, server: ' . mysqli_get_server_info($link);
The mysqli_report line is needed on PHP 8.1 and newer, where a failed connection otherwise throws an exception instead of readable text. Delete the file right after the test, because it contains your database password.
| Code | Error text | Meaning | Fix |
|---|---|---|---|
| 1045 | Access denied for user ‘user’@’localhost’ (using password: YES) | Wrong user or password, or no user for this host | Reset the password, update wp-config.php |
| 1044 | Access denied for user … to database … | User exists but has no rights to the database | Assign the user to the database, grant privileges |
| 1049 | Unknown database | No database with this name | Check DB_NAME and prefix, import the dump |
| 2002 | No such file or directory, Connection refused or getaddrinfo failed | No socket, server not running or host not found | Check the MySQL service, try 127.0.0.1, verify DB_HOST |
| 1040 | Too many connections | Server-wide connection limit reached | Find the source of load, contact your host |
| 1203 | User … already has more than ‘max_user_connections’ active connections | Your per-user connection limit reached | Cache, bot protection, a bigger plan |
When you contact support, include the URL, the exact time of the error, what changed before it and the test script output.
How to prevent it from happening again
- Back up the database separately and test a restore.
- Set up uptime monitoring: WordPress returns status 500 on this error, so any status check will catch it.
- Enable page caching and protect wp-login.php and xmlrpc.php.
- Run regular database optimization: bloated options, revisions and transients keep connections busy longer.
- Watch free disk space and inodes: a full disk stops the database.
- Never set 777 on wp-config.php or leave copies of it in public folders.

Prepare a custom outage page too: WordPress shows wp-content/db-error.php instead of the default message, and a 503 status with Retry-After tells search engines the outage is temporary:
<?php
http_response_code(503);
header('Retry-After: 600');
?>
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><title>Maintenance</title></head>
<body><h1>We will be back shortly</h1><p>We are already working on it. Please try again in a few minutes.</p></body></html>
FAQ
Can this error cause data loss?
The error itself deletes nothing. The risk comes from repairs, innodb_force_recovery or reinstalling, so back up first.
Why does the error appear and disappear?
Almost always because of limits reached during peaks. Compare the error times with access logs and look for bots, cron runs and heavy admin tasks.
The site works, but the admin says tables are unavailable. What now?
Some tables are damaged or missing. Back up the database, enable WP_ALLOW_REPAIR, run /wp-admin/maint/repair.php and remove the constant afterwards.
Why did the error appear after moving a multisite to a new domain?
A network looks up its domain in DOMAIN_CURRENT_SITE and the wp_site and wp_blogs tables. If the old domain is still there, you get this error with a Could not find site note. Update all three.
Conclusion
Error establishing a database connection looks scary, but the cause is usually found in minutes: read the message in /wp-admin/, compare wp-config.php with the panel, test the phpMyAdmin login and run the test script. If it keeps coming back, look at limits and load. A site that constantly hits resource caps needs a bigger plan: RichHost hosting plans run on NVMe disks with our own control panel and its AI assistant, start at $8 per month for A3 and come with 10% off for yearly payment. For a wider view of pricing, see our guide to web hosting cost. What a WordPress site needs from a host is summed up on our WordPress hosting page.



