Apache 500 Internal Server Error: how to find the cause and fix it

A 500 from Apache is a generic "something went wrong" status, so the error page itself does not tell you the cause. The reason is written in the Apache error log. Read it first, then check the file or directive it names, such as a `.htaccess` file or a failing script.

Applies to:Apache HTTP Server2.4 (documentation used); the approach applies to other versions
On this page

What it means

HTTP 500 is a catch-all. It means the server hit an unexpected condition and had no more specific 5xx code to describe it. Apache has no separate "Apache 500" error: it is the standard status, and the browser usually shows "Internal Server Error" with the text "The server encountered an internal error or misconfiguration and was unable to complete your request."

Because the status says nothing about the cause, guessing wastes time. Apache records the real reason in its error log, normally as one line that names a file and a problem. The fixes below start with finding that line, then go through the usual suspects.

If your site sits behind Nginx instead, see Nginx 502 Bad Gateway.

Symptoms and causes

You are likely dealing with this problem if:

  • The browser shows "Internal Server Error" instead of your page.
  • The whole site fails, or only one directory or script does.
  • The error log contains lines such as .htaccess: RewriteCond: bad flag delimiters, .htaccess: DirectoryIndex not allowed here or Premature end of script headers.

The usual causes, most common first:

A bad .htaccess file
A syntax error (for example in a RewriteRule or RewriteCond), a directive that is not allowed there because AllowOverride is too restrictive, a directive that is never permitted in .htaccess (such as <Directory> or Alias), or a directive from a module that is not loaded (logged as "Invalid command").
CGI or script failures
"Premature end of script headers" usually means a wrong shebang path, Windows (CRLF) line endings, a missing Content-Type header and blank line, or stray output before the headers. A script that is not executable or breaks a suexec policy also fails.
Application errors behind Apache
A PHP or other application error can end as a 500. The application's own log is the place to look; the exact causes depend on your setup.
File permissions or ownership
Apache runs as an unprivileged user, so files and folders it cannot read or execute produce errors.
Main configuration problems
A missing module or a broken directive in the main config.
Resource exhaustion
The server running out of memory can also return a 500.

How to fix it

Work through these in order. They start with the quickest, safest checks and move to deeper repairs; stop as soon as the problem is gone.

1.Read the Apache error log

Easy

The log names the file and the problem, which turns a vague 500 into a specific fix.

  1. Find the log. The path is set by the ErrorLog directive. Typical locations are /var/log/apache2/error.log (Debian, Ubuntu), /var/log/httpd/error_log (RHEL, CentOS) and <ServerRoot>/logs/error_log (source builds). Paths differ by distribution. To see which path your config uses, you can search the config folders (adjust the folder names to your system):
    Terminalneeds sudo / root
    grep -ri ErrorLog /etc/apache2 /etc/httpd
  2. Watch the log live while you reload the failing page in your browser (use your own log path).
    Terminalneeds sudo / root
    tail -f /var/log/apache2/error.log
  3. Read the newest line. It usually points to a file such as .htaccess or a script. On shared hosting you may not reach the main log: use your control panel's log viewer (for example the Errors page in cPanel).

2.Increase log detail for one module

Moderate

Helps when the message is unclear, for example with rewrite rules.

  1. Add a module-specific log level to your Apache config, for example:
    Apache config
    LogLevel info rewrite:trace5
  2. Reload Apache (the service is called apache2 on Debian-family systems and httpd on RHEL-family ones), reproduce the error and read the log again. Set the level back afterwards, as trace output is large.
    Terminalneeds sudo / root
    sudo systemctl reload apache2

3.Rule out the .htaccess file

EasyChanges settings

A faulty .htaccess is a frequent culprit when the log points to it, and renaming it is an easy test.

Before you start: Do this on a staging copy or at a quiet time. .htaccess often holds access control (Require, AuthType, blocks on config or backup files) and security rewrites, and all of those are inactive while the file is renamed, so private content may be exposed. Rename it back immediately after the test.

  1. Rename the file in the folder that fails, then reload the page.
    Terminal
    mv .htaccess .htaccess.bak
  2. Restore the file straight away, whatever the result.
    Terminal
    mv .htaccess.bak .htaccess
  3. If the site loaded while the file was renamed, the problem is in that file. Fix the directive named in the error log.
  4. If the log says a directive is "not allowed here", AllowOverride is too strict for it. Prefer moving the rules into the main server config. If they must stay in .htaccess, allow only what is needed with AllowOverrideList, or a minimal AllowOverride value (for example FileInfo for rewrite rules). Avoid AllowOverride All: it lets anyone who can write a .htaccess file change server behaviour, which matters most on shared or multi-user servers.
  5. To check whether .htaccess is read at all, add a nonsense word to it. A 500 means it is read. No error means AllowOverride None is in effect. Remove the word afterwards.

4.Test the configuration and modules

Easy

Catches syntax errors and missing modules, including the "Invalid command" case.

  1. Run the built-in syntax check (some systems use apache2ctl -t instead).
    Terminalneeds sudo / root
    apachectl configtest
  2. If a directive needs a module that is not loaded, enable it. The a2enmod tool exists on Debian-family systems only; on other systems add the matching LoadModule line instead.
    Terminalneeds sudo / root
    sudo a2enmod rewrite
  3. Reload Apache after any change.
    Terminalneeds sudo / root
    sudo systemctl reload apache2

5.Fix a failing CGI script

Moderate

Needed when the log says "Premature end of script headers".

  1. Make the script executable.
    Terminal
    chmod a+x script.cgi
  2. Check that the shebang line (first line of the script) points to a real interpreter.
    Terminal
    command -v python3
  3. Remove Windows line endings if the file was edited on Windows.
    Terminal
    dos2unix script.cgi
  4. Run the script directly. The very first output must be a header such as Content-Type: text/html, followed by a blank line, with no error text or traceback before it.
    Terminal
    ./script.cgi
  5. If suexec is in use, check where it lives and what it allows.
    Terminalneeds sudo / root
    apachectl -V | grep SUEXEC_BIN
    suexec -V

6.Check permissions and ownership

ModerateChanges settings

Apache runs as an unprivileged user and must be able to read your files and enter your folders.

Before you start: Note the current permissions before changing them, and never apply a blanket chmod -R on a whole site without knowing what is there.

  1. List the permissions and owner of the failing file and its parent folders.
    Terminal
    ls -l /var/www/html
  2. Make sure the web server user can read the files and enter the folders, and that scripts which must run (CGI) have the execute bit. A common convention is 755 for folders and 644 for files, but the right values depend on who owns the files and which user Apache runs as.

7.Check the PHP or application log

Moderate

If Apache only reports a generic failure, the application may have logged the real error.

  1. Open the PHP error log, PHP-FPM log or your application's own log and look for fatal errors or other failures around the time of the request.
  2. On a CMS such as WordPress, disable recently added plugins or themes, then test again. Treat this as a pointer: exact log locations depend on your setup.

Check that it worked

  • Reload the page: it returns your content instead of "Internal Server Error".
  • apachectl configtest reports Syntax OK.
  • The error log shows no new errors while you load the page.

If it still fails

  • Re-read the newest error log line: it should name a file or directive, and that is where to look next.
  • If you cannot access the main log (shared hosting), ask your host's support for the error log entry for the failing request time.
  • If the site is behind a proxy or PHP-FPM, check the backend's own log too, since a backend 500 can be passed through to the browser.

Questions

Why does Apache work on one host but give a 500 on another with the same .htaccess?

The hosts may differ in their AllowOverride settings or in which modules are loaded. A directive that one server allows can be rejected by another.

Sources

  1. Log FilesOfficial · Apache Software Foundation
  2. Apache HTTP Server Tutorial: .htaccess filesOfficial · Apache Software Foundation
  3. Apache Tutorial: Dynamic Content with CGIOfficial · Apache Software Foundation
  4. 500 Internal Server ErrorOfficial · MDN Web Docs