Fixing "Error Establishing a Database Connection" in WordPress: A Symptom-First Diagnostic
A symptom-first diagnostic for the WordPress "Error establishing a database connection" condition: map what you see to a cause, test credentials, host/socket behavior, service health, and host-level blocks, then apply the matching fix.
25 Jan 2026, 11:49 UTC

The condition and what it actually means
Every page — front end and wp-admin — shows "Error establishing a database connection" instead of site content. The useful takeaway: PHP is executing, but WordPress cannot complete the initial connection to the MySQL or MariaDB server. That narrows the suspects to four things: the credentials in wp-config.php, the host definition, the database service itself, or the network path between them. Themes, plugins, and the WordPress admin area are not involved at this stage, so do not start there.
One scope note before diagnosing: this error means the connection itself failed. Problems that occur after a successful connection — missing table privileges, corrupted tables such as wp_options, or query errors — produce different symptoms (partial pages, query errors, or a blank screen), not this message. Keep that boundary in mind so you do not chase the wrong layer.
Access you will need, by check
Not every check requires the same access. Credential comparison and the PHP connection test work on shared hosting with only file access (FTP or a file manager). Service-status and log checks require shell access with sudo on the database host — on shared hosting, those become escalation items for your provider. Where a shell-only check has a control-panel alternative (such as phpMyAdmin), it is noted below.
Symptom-to-cause map
| Observable symptom | Likely cause | First check |
|---|---|---|
| Error on all pages, appeared after a config edit or migration | Wrong DB_NAME, DB_USER, DB_PASSWORD, or DB_HOST in wp-config.php | Compare constants to hosting control panel values |
| Error after moving servers or upgrading PHP | DB_HOST form mismatch: localhost (socket) vs 127.0.0.1 (TCP) vs remote hostname | PHP connection test with each host form (check 3) |
| Error is intermittent, worse under traffic | Database service restarting, hitting max_connections, or being killed for memory | Service status and error log (check 4) |
| Error appeared right after a database password change | wp-config.php not updated, or the password was changed on a different user@host entry | Manual login with the exact constants (check 2) |
| CLI login works but PHP fails with identical parameters | Socket-path mismatch, driver difference, or a host-based block (firewall, SELinux) | PHP connection test and firewall/SELinux check (checks 3 and 5) |
Ordered checks
1. Collect the constants without changing them
Open wp-config.php on the web server and note DB_NAME, DB_USER, DB_PASSWORD, and DB_HOST. Do not edit yet. Compare them against the database credentials shown in your hosting control panel or provisioning records. If you later edit this file, back it up first — a PHP syntax error here produces a blank page instead of a readable error. Also edit with a plain-text editor: saving from some Windows editors can prepend an invisible UTF-8 byte-order mark (BOM), which breaks the file in hard-to-diagnose ways.
2. Test the exact credentials with a real login
With shell access: run this from the web server shell, so you test from the same network position PHP uses. Replace the placeholders with the actual values from wp-config.php:
mysql -u DB_USER -p -h DB_HOST DB_NAMEExpected: a password prompt, then a successful login. "Access denied" points to wrong credentials or a user defined for a different host (MySQL accounts are user-plus-host, so 'wpuser'@'localhost' and 'wpuser'@'%' are separate accounts). "Can't connect" points to a host, socket, or network problem. Let -p prompt for the password rather than typing it on the command line, which exposes it in shell history.
Without shell access: log into phpMyAdmin (or your provider's equivalent) using the same credentials. A successful login there confirms the credentials are valid; a failure confirms they are the problem.
3. Test host and socket behavior from PHP
With the mysqli driver, the hostname localhost typically selects a Unix socket, while 127.0.0.1 forces a TCP connection. If the socket path differs from the PHP default — common when MySQL and MariaDB distributions use different default socket locations — one form works and the other fails. Create a temporary file, dbtest.php, outside the public web root if possible:
<?php
// Replace each placeholder with the value from wp-config.php
$mysqli = new mysqli('DB_HOST', 'DB_USER', 'DB_PASSWORD', 'DB_NAME');
if ($mysqli->connect_errno) {
echo 'FAILED: ' . $mysqli->connect_error;
} else {
echo 'CONNECTED';
$mysqli->close();
}Run it with php dbtest.php from the shell, or briefly via the browser if it must sit in the web root. Test with DB_HOST set to each of localhost, 127.0.0.1, and (if applicable) the remote hostname. Expected: whichever form connects here is the one wp-config.php should use. Risk: this file contains credentials — delete it immediately after testing and never leave it web-reachable.
4. Check the database service and its error log
Requires shell access with sudo on the database host. Service names vary by distribution:
sudo systemctl status mysql
# or, on MariaDB-based systems:
sudo systemctl status mariadbExpected: active (running). If it is down or restarting repeatedly, inspect the error log — commonly /var/log/mysql/error.log or /var/log/mariadb/mariadb.log, though paths vary — for "Out of memory", "Too many connections", or InnoDB recovery messages. Restarting a production database causes brief downtime; do it in a maintenance window. On shared hosting, ask your provider to perform this check instead.
5. Check for host-level blocks on TCP connections
If the CLI test fails with "Can't connect" over TCP but the service is running, something is blocking the path. On the database host, verify MySQL is listening on the expected interface (ss -ltn | grep 3306), check firewall rules permitting TCP 3306 from the web server, and on SELinux-enforcing systems check whether the web server is permitted to make network database connections (getsebool httpd_can_network_connect_db; a denied boolean is a classic cause of PHP-only connection failures on RHEL-family systems). AppArmor profiles can similarly restrict the MySQL service itself. These are shell-and-sudo checks; on managed hosting, report the CLI-works/PHP-fails split to your provider.
6. Check connection limits for intermittent failures
If the error only appears under load, query the live limits from a privileged MySQL session (or phpMyAdmin's SQL tab):
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Max_used_connections';If Max_used_connections approaches max_connections, the error log will usually show "Too many connections". Fixes include raising max_connections, reducing PHP-FPM pool sizes so workers cannot hold more connections than the database allows, or finding slow queries that hold connections open.
Fixes tied to findings
Credential mismatch: update DB_USER, DB_PASSWORD, and DB_NAME in wp-config.php to match the provider's values, save with a plain-text editor, and reload the site.
Host form mismatch: set DB_HOST to whichever form succeeded in check 3. For a remote database, also confirm the MySQL account exists for the web server's host and that TCP 3306 is permitted between the two machines.
Service down or resource exhaustion: restart in a maintenance window, then fix the root cause shown in the logs — memory, connection limits, or disk space — rather than relying on restarts.
Host-level block: adjust the firewall, or set the appropriate SELinux boolean (for example setsebool -P httpd_can_network_connect_db 1 where that is the confirmed cause).
Escalation criteria
Escalate to your provider or a DBA when: the database service will not start; logs show disk-full or InnoDB corruption; you lack the shell or sudo access checks 4–6 require; or the CLI login succeeds but PHP fails with identical parameters after you have ruled out the socket-path and SELinux/firewall causes above — at that point the discrepancy lives in the platform's PHP build or driver configuration, which only the platform owner can inspect.
Limitations and verification
This guide assumes WordPress core against MySQL or MariaDB. Service names, log paths, default socket locations, and default authentication plugins vary by distribution, database version, and hosting platform — confirm them on your stack before acting. After each fix, verify by reloading the front page and logging into wp-admin; the error should be gone and stay gone across several page loads. This draft is based on general platform knowledge, not live testing; treat environment-specific values as placeholders to confirm on your system.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.