Guide Errors & Troubleshooting

How to fix a 500 internal server error

The least informative error on the web. The real message is always in a log — here is how to find it and what it usually says.

Updated 8 min read Intermediate

A 500 internal server error is the web's way of saying "something went wrong and I am not going to tell you what". It is not a diagnosis. It is the server declining to show a visitor a real error message, which is the correct behaviour — the real message often contains file paths and database names that should never be public.

The real message still exists. It is in a log. Everything below is about finding it, and then dealing with what it says.

Start with the log, not with guessing

Almost every guide to this error lists five fixes and invites you to try them all. That works eventually, but reading the log usually tells you the answer in thirty seconds.

In your hosting control panel, find the error log for your site. You are looking at the most recent entries, which will name a file and a line number. A typical entry looks like this:

PHP Fatal error:  Uncaught Error: Call to undefined function wp_kses()
  in /home/site/public_html/wp-content/plugins/example/init.php:42

That tells you the file, the line, and the plugin. There is nothing left to guess.

If the log is empty

An empty log usually means the failure happened before PHP started — which points at .htaccess or at permissions, both covered below. It can also mean logging is off for the account, in which case ask support to enable it.

The five usual causes

1. A broken .htaccess file

Apache reads .htaccess on every request. One invalid directive — often a rule pasted from a guide for a different server, or a module your hosting does not load — makes every request in that folder fail immediately.

Test it by renaming rather than deleting:

  1. Rename the file

    In the file manager, rename .htaccess in your site root to .htaccess-off. If you cannot see it, turn on hidden files — a leading dot hides it by default.

  2. Reload the site

    If the error clears, the file was the cause. If nothing changes, rename it back and move on to the next cause; you have ruled one out.

  3. Find the offending line

    Restore the file and comment out blocks with a # at the start of each line until the site returns. WordPress will regenerate a clean default file if you delete it and re-save your permalink settings.

2. File and folder permissions

Servers refuse to execute scripts that are writable by anyone other than their owner — a script that everyone can write is a script anyone can replace.

TypePermissionMeaning
Folders755You can write; everyone else can read and enter
Files644You can write; everyone else can read
Never777Anyone can write. Many servers refuse to run these at all

A 500 that started right after a manual upload or a restore is very often a permissions problem, because some FTP clients do not preserve modes.

3. Running out of memory

When PHP exceeds its memory limit it aborts mid-request, and the aborted request frequently surfaces as a 500 rather than as an obvious memory error. The log entry mentions "allowed memory size".

Raise the limit in your control panel's PHP settings, or in php.ini:

memory_limit = 256M

Treat this as a diagnostic rather than a fix. Something is using the memory, and doubling the ceiling only buys time if a plugin is genuinely leaking.

4. Code that changed recently

If the error appeared after an update, an install or an edit, that is your cause. The log names the file. Disable that plugin, revert that theme, or restore that file.

On WordPress, when the admin area is also throwing the 500, you can disable plugins without logging in: rename wp-content/plugins to plugins-off. Every plugin deactivates at once. Rename it back and they reappear, deactivated, so you can enable them one at a time to find the culprit.

5. A script hitting the execution time limit

Long-running imports, backups and migrations are the usual victims. The log mentions "maximum execution time". Raise max_execution_time for that operation, or better, run the job from the command line where the limit does not apply.

Turning on the real error temporarily

If the log is genuinely unhelpful, you can make PHP show the error on screen — briefly, and never on a site with real visitors:

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

On WordPress the equivalent is WP_DEBUG with WP_DEBUG_LOG in wp-config.php, which writes to wp-content/debug.log instead of the screen — safer on a live site.

Turn it off again

Displayed errors expose absolute paths, database names and occasionally credentials, and they are indexed by search engines when they appear on a public page. Switch them off the moment you have your answer.

If you have exhausted all of that

Collect three things before asking for help: the exact time the error last happened, the URL that produced it, and the last few lines of the error log. With those, support can match your request against the server-side logs immediately instead of asking you to reproduce it.

Frequently asked questions

Is a 500 error my fault or the host's?

Usually the site's rather than the server's. A 500 means a request reached the server and something in handling it failed — most often application code, a directive in .htaccess, or a resource limit. If every site on the account is affected at once and nothing changed, that shifts the balance towards a platform problem worth reporting.

Why do I get a 500 instead of a useful message?

Because showing the real error to the public would leak file paths, database names and sometimes credentials. The server deliberately returns a generic page and writes the detail to a log only you can read.

The error comes and goes. What does that mean?

Intermittent 500s point at a resource limit rather than broken code — memory, execution time, or database connections — because those are only exceeded under load. Broken code fails every time.

Related reading