500 Internal Server Error: What It Means and How to Fix It
A 500 Internal Server Error means the server accepted the request and then failed to build the page. Find the real cause in the logs — not on the screen.
A 500 Internal Server Error is the server admitting it broke. The request arrived, the server accepted it, and then something went wrong while producing the response. Unlike the gateway errors, nothing in front of your site gave up — the application itself failed.
That is also why a 500 is the least helpful error in the whole family. It is deliberately vague: the specification says the server hit “an unexpected condition”, and almost every platform returns a generic page rather than naming the fault. The message on the screen is useless. The log is where the answer is.
How 500 differs from the gateway errors
The four common 5xx codes look similar to a visitor and mean completely different things to whoever has to fix them:
- 500 Internal Server Error — the application was asked to build the page and threw an error. The fault is in your code, configuration, or a dependency it needs.
- 502 Bad Gateway — a proxy got an unusable answer from the server behind it. The fault is usually a dead or crashing process.
- 503 Service Unavailable — the server is deliberately or temporarily refusing work. Often overload or maintenance.
- 504 Gateway Timeout — the server was alive but too slow, and the proxy stopped waiting.
The practical test: a 502, 503, or 504 is raised by the layer in front of your application, and a 500 is raised by it. So a 500 means your application is running — which is good news, and also means the diagnosis has to happen inside it.
Start with the log, not the page
The generic error page will never tell you what happened. Three places will:
| Source | What it shows | How to reach it |
|---|---|---|
| Web server error log | PHP fatal errors, permission denials, malformed configuration | nginx/apache error log, or your host’s log viewer |
| Application log | Stack traces with file and line numbers | wp-content/debug.log, storage/logs/, or your framework’s log |
| Host panel | Resource-limit suspensions and restarts | cPanel, Plesk, or your platform’s dashboard |
Read the timestamp against your own. A 500 with no log entry at all is itself a diagnosis: the request failed before your application code ran, which points at the web server configuration, a permissions problem, or a resource limit imposed by the host.
The usual causes
A fatal error in application code
The most common cause, and the easiest to confirm. A PHP fatal error, an unhandled exception in any language, or a syntax error in a file that was just edited stops the response before it is built. The log names the file and the line.
Fix: read the log line. If it appeared right after an edit or a deploy, you already know where to look. Revert the change, then fix it properly rather than leaving a half-applied edit in place.
A broken .htaccess file
On Apache, a single malformed directive in .htaccess takes down the entire site with a 500 — every page, including the admin. The giveaway is a 500 that appears instantly on every URL with a log line naming the configuration file.
Fix: rename .htaccess to .htaccess.bak and reload. If the site comes back, the file was the cause; restore it in pieces to find the bad line. The usual culprits are a redirect block pasted in with a typo, or PHP directives the host does not permit.
A plugin or theme conflict
The classic WordPress cause, and the reason the fix is always “disable everything and re-enable one at a time.” Two plugins claiming the same function, or a theme update that broke an assumption a plugin relied on, produce a fatal error on the pages that use both.
Fix: rename the plugins directory to disable all of them at once — faster than clicking through the admin, which may itself be returning 500. If the site recovers, rename it back and deactivate plugins one at a time until the 500 returns.
The memory limit was exceeded
A request that needs more memory than PHP is allowed gets killed mid-response. This one is load-dependent, so it looks intermittent: the same page works when it is quiet and 500s under traffic or with a large import.
Fix: raise WP_MEMORY_LIMIT (or memory_limit) and check the log for the “allowed memory size exhausted” line. Raising it without finding out which operation needs the memory defers the problem; the usual offenders are a plugin loading an entire table into memory, or a page builder on a page with too many blocks.
The database connection failed
The application cannot reach its database, so it fails while building the page. Credentials changed by a host migration, a database that has been suspended for exceeding a quota, or a localhost that no longer resolves inside a container all produce this.
Fix: confirm the database is running and reachable from the application host, and that the credentials in the config file match. A host migration that moves the database to a new hostname is the standard cause — the config file still points at the old one.
File permissions
A file the web server cannot read, or a directory it cannot enter, produces a 500 with a permission-denied line in the log. This follows a manual file upload, an unzip, or a migration that preserved the wrong ownership.
Fix: files should be 644 and directories 755, owned by the web server user. Resist 777 — it is a security problem that hides the real ownership fault rather than fixing it.
A version mismatch after an upgrade
An application updated to a version that requires a newer PHP than the host provides — or a host that upgraded PHP past what the application supports — fails at the first line that uses a removed feature. It often looks sudden and unexplained.
Fix: check what PHP version the site is actually running against what the application requires. This is one of the few 500s where the fix is a configuration change rather than a code change.
If it is a WordPress site
WordPress deserves its own list because it produces most of the 500s on the web, and its diagnosis is well-trodden:
- Get the actual error. Add
define('WP_DEBUG', true);anddefine('WP_DEBUG_LOG', true);towp-config.php— on staging, not production, because debug output on a live site leaks file paths and configuration to visitors. The log appears atwp-content/debug.log. - Disable all plugins by renaming the
pluginsfolder, then re-enable one at a time. - Switch to a default theme (Twenty Twenty-Four or similar). If the 500 stops, the theme is the cause.
- Re-save permalinks at Settings → Permalinks, which rebuilds the rewrite rules and fixes some 500s caused by a corrupt rewrite set.
- Raise the memory limit if the log says memory was exhausted.
- Check
.htaccessas described above.
A “There has been a critical error on this website” notice is WordPress’s generic wrapper around a fatal error. It is a 500 with a friendlier face, and the same steps apply — WordPress emails the site admin the underlying error when debug logging is on.
Confirming the fix
- The specific URL that failed now returns 200, checked with
curl -sI https://example.com/broken-page | head -1rather than by looking at the page. - The error log stops recording entries for that route — check timestamps, not the file size.
- The page works logged-out, in a fresh session. Many 500s are triggered by a plugin’s admin path or a stale session and look fixed when you are logged in.
- It survives the condition that caused it. If the 500 was memory or load-related, replay it under the same conditions; a fix that only works on an idle server is not a fix.
Why a repeating 500 is expensive
A 500 tells a crawler the failure is the server’s, not the page’s. Crawlers treat it as temporary and come back — which sounds forgiving, but means the URL keeps consuming crawl budget without ever being confirmed. A site returning 500s across many URLs is a site that gets crawled less, which slows the discovery and refresh of everything else.
The pattern matters more than the incident. A 500 on one URL after a deploy is a mistake. A 500 that returns weekly on the same page is a bug that is being papered over each time. And a 500 that appears only under traffic is a capacity problem that will eventually be seen by customers rather than by you.
All three are visible from outside, without instrumenting the application. SitesRadar’s free plan checks one site on a schedule and emails you when it starts returning 5xx, alongside uptime, SSL expiry, DNS, and broken links. If you look after several client sites, the client site down triage checklist is the order to work through when the alert arrives.
FAQ
Is a 500 error my fault or my host’s?
It depends on what the log says. A fatal error in your code or a plugin is yours. A permission problem, a suspended database, or a PHP version the host changed is theirs. The log line usually names which side of that line you are on, which is why reading it first saves a support ticket.
Why does my site show a 500 only sometimes?
Intermittent 500s are almost always resource-related — a memory limit hit by one heavy operation, or a database connection pool exhausted under load. A 500 that happens on the same URL every time is deterministic and therefore a code or configuration fault.
Can I bypass a 500 error?
No, and there is nothing to click through. Unlike a certificate warning, a 500 is not a decision the browser made; the server genuinely failed to produce a page. There is no content to show.
Does a 500 error hurt SEO?
Repeated ones can. Crawlers treat a single 500 as temporary, but a site that returns them regularly is crawled less often and can have URLs dropped from the index if the condition persists. A one-off during a deploy is recovered from quickly.
What is the difference between 500 and 502?
A 500 comes from your application: it received the request and failed while building the page. A 502 comes from the proxy in front of it, which got an unusable answer. A 500 means your application is running; a 502 often means it is not.
How do I find the cause if there is no log entry?
No log entry usually means the request never reached your application. Check the web server configuration, file permissions, and whether the host has suspended the account for exceeding a plan limit — those all fail before any application code runs.