Fixing 500 Internal Server Errors
A 500 Internal Server Error is the server admitting that something went wrong while building the page, without saying what. It is a catch-all: a typing mistake in a PHP file, a plugin calling a function that no longer exists, a script running out of memory and a broken rewrite rule can all produce exactly the same blank error.
Guessing wastes hours. This guide shows where the real error message is written down, how to read it, and how to fix the causes that account for most 500 errors on small business sites.
Why a 500 tells you so little
Every other common status code carries a clue. A 404 says the address is wrong, a 403 says a rule refused you, a 504 says something was too slow. A 500 only says that the software handling the request failed before it could finish. The web server deliberately hides the details from visitors, because error messages can reveal file paths, database names and code that attackers find useful.
So the details go somewhere else: a log file. The single most important habit when fixing a 500 is to stop reloading the page and go and read that log. The message there usually names the file, the line number and the reason, and most fixes take minutes once you have it.
Before opening logs, collect three facts from the audit and a quick test, because they narrow the search considerably:
- Scope. Does every page fail, one template (all product pages, all blog posts), or a single URL? Site-wide failures point at configuration, the PHP version or the database. One template points at code used only there.
- Timing. Did it start at a particular moment? Line it up with plugin updates, a deploy, a PHP version change by your host, or a certificate renewal that restarted services.
- Consistency. Does the same URL fail every time, or only sometimes? Constant failures are code or configuration. Occasional failures under load tend to be memory, database connections or a dependency that sometimes times out.
Where the real error is written
There are usually two or three logs involved, and the message can be in any of them. Check them in this order.
| Log | Typical location | What you find there |
|---|---|---|
| Web server error log | /var/log/apache2/error.log, /var/log/httpd/error_log
or /var/log/nginx/error.log; per-site logs on managed hosting | Configuration and
.htaccess errors, and PHP errors when PHP runs inside Apache |
| PHP-FPM log | Often under /var/log/ with the PHP version in the name | Worker crashes and pool problems; PHP messages may also be passed to the web server log |
PHP error_log setting | Wherever error_log in php.ini
points; some hosts write a file called error_log next to the script | Fatal errors, parse errors, memory limits, uncaught exceptions |
| Application log | For example storage/logs/ in Laravel, wp-content/debug.log
in WordPress when enabled | Exceptions caught by the framework, with a stack trace |
Follow the log live while you load the failing page. This makes it obvious which line belongs to your request:
sudo tail -f /var/log/nginx/error.log /var/log/php8.3-fpm.log
# then load https://www.example.co.uk/shop/basket/ in the browser
If you do not know where PHP is logging, ask PHP itself. Create a temporary file with <?php phpinfo();,
load it once, search for error_log and log_errors, then delete the file straight
away, because it exposes your server configuration.
When the log is empty
If nothing appears, logging is probably switched off. Turn it on without showing errors to visitors:
; php.ini or the per-site PHP settings in your hosting panel
display_errors = Off
log_errors = On
error_reporting = E_ALL
error_log = /var/www/example/logs/php_errors.log
display_errors on a live site to see the message,
even briefly. Search engines and visitors may capture the output, and it can include database credentials
in a stack trace. Log to a file and read the file.Messages you will see, and what they mean
| Message in the log | Cause | Usual fix |
|---|---|---|
PHP Parse error: syntax error, unexpected ... | A typing mistake in a PHP file, often from a hand edit | Fix the named line, or restore the file from a backup |
PHP Fatal error: Uncaught Error: Call to undefined function | Code relies on a function from a missing PHP extension, a removed feature, or another plugin | Install the extension, update the code, or restore the dependency |
Allowed memory size of ... bytes exhausted | The script used more memory than
memory_limit allows | Find what is loading so much; raise the limit modestly if the need is genuine |
Invalid command 'php_value' | An .htaccess file sets PHP options,
but PHP is not running as an Apache module | Move the setting to php.ini, .user.ini
or the hosting panel |
Request exceeded the limit of 10 internal redirects | A rewrite rule keeps matching its own output | Add a condition so the rule skips existing files or already-rewritten paths |
RewriteRule: bad flag delimiters or Invalid command | A malformed
or unsupported line in .htaccess | Correct the line, or enable the missing Apache module |
SQLSTATE[HY000] [2002] or Access denied for user | The database server is down, unreachable, or the password changed | Check the database service and the connection details in the config file |
No space left on device | The disk is full, so sessions, caches and logs cannot be written | Clear old logs, backups and caches; add space |
Primary script unknown (nginx) | nginx passed a path PHP-FPM cannot find, often after moving the site | Correct root and SCRIPT_FILENAME in the
server block |
After a PHP version change
Hosts regularly retire old PHP versions, and each major version removes functions that older plugins and themes relied on. If 500 errors appeared across a site on a day you did not change anything, check whether the PHP version was changed for you. The quick relief is to switch back to the previous version in your hosting panel, if it is still offered; the lasting fix is to update or replace the code that fails, since the old version will eventually be removed.
Testing a suspect .htaccess file
cd /var/www/example/public
cp .htaccess .htaccess.backup
mv .htaccess .htaccess.off
# reload the page: if the 500 is gone, the file is the cause
# restore it and remove blocks one at a time until the error returns
mv .htaccess.off .htaccess
Removing the file also removes your redirects and any access rules, so do this quickly and put it back. On a busy site, test on a copy instead.
The fix, step by step
Step 1
Note when and where it fails
Use
the HTTP Error Audit results to see which URLs returned 500 and at what time. Group them: every page,
one template, or a single address. Then check whether the failure repeats by requesting one of them with
curl -sI several times. Write down the exact time of a failing request, because you will
use it to find the matching line in the logs in the next step.
Step 2
Find the log that holds the message
Open
the web server error log first, then the PHP-FPM log and the file named by the PHP error_log
setting, then the application log such as Laravel's storage/logs. Run tail -f
on them while you reload the failing page so the new line stands out. On managed hosting, use the per-site
logs in the control panel, which are often more complete than the summary view.
Step 3
Turn on logging if it is silent
If
no log shows anything, set log_errors to On, error_reporting to E_ALL and error_log
to a writable file outside the web root, while keeping display_errors Off so visitors never
see the output. Apply the change in php.ini, a .user.ini file or your hosting
panel, reload PHP if needed, then request the failing page again and read the new file from the top.
Step 4
Match the message to its cause
Read
the first error for the request, not the last, because later lines are often knock-on effects. A parse
error names a file and line, an undefined function points at a missing extension or removed plugin, Allowed
memory size exhausted is a memory problem, Invalid command or internal
redirects is .htaccess, and SQLSTATE is the database. Note which
plugin, theme or file the path belongs to.
Step 5
Fix the cause, not the symptom
Correct
the broken line or restore the file from backup, update or remove the plugin that calls a missing function,
move php_value lines out of .htaccess, or add a condition to a looping rewrite
rule. Raise memory_limit only after checking what uses the memory. For database errors,
confirm the database service is running and that the credentials in the config file still match.
Step 6
Check that errors return a real 500
Reload the page and confirm a 200, then re-run the HTTP Error Audit for the affected
URLs. While you are there, make sure your custom error page still sends a genuine 500 status rather than
a 200, so search engines do not index an error message as content. Finally, remove any temporary phpinfo
file and restore normal log settings if you changed them.
Error pages that lie about their status
Some sites catch errors and show a friendly "Something went wrong" page, but send it with a 200 status. Visitors see an apology, while search engines see a successful page with thin content, and can index it in place of the real one. Monitoring tools that only check the status code also report the page as healthy. The reverse happens too: an application catches an exception deep inside, logs nothing, and returns a half-built page with a 200.
Check what your error page really sends:
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.co.uk/shop/basket/
In a framework, the error handler should render the friendly page with a 500 status. In plain PHP, set the code before any output:
<?php
http_response_code(500);
include __DIR__ . '/templates/error-500.html';
exit;
For planned maintenance, a 503 with a Retry-After header is the right code, not a 500,
because it tells crawlers the outage is temporary and deliberate.
Notes for common set-ups
- WordPress. Most WordPress 500s are plugin or theme fatal errors, and WordPress's recovery mode may email the site admin with the plugin name. The WordPress HTTP errors guide covers debug.log and disabling plugins without the dashboard.
- Laravel. Check
storage/logs/laravel.log. A 500 straight after deploying often means thestorageorbootstrap/cachefolders are not writable, a missingAPP_KEY, or a stale configuration cache. - Django and Flask. With debug turned off, errors go to the logging configuration
or to the application server's log, such as gunicorn's error log. Never leave Django's
DEBUGon in production to see errors. - Node.js and Next.js. Unhandled exceptions and failed server-side data fetching are covered in the Node.js and Next.js guide.
- Plesk and cPanel. The per-domain logs and PHP settings pages are the fastest route; the Plesk and cPanel guide shows where they are.
How 500 errors affect search
A page that returns 500 cannot be indexed while it fails, but a short, occasional failure is not a disaster. Search engines expect servers to fail now and then and will try again. What causes damage is persistence and scale:
- Crawl slowdown. When a site keeps answering with server errors, Google reduces how fast it crawls, so new and updated pages are picked up more slowly.
- Dropped pages. URLs that return server errors for an extended period can be removed from the index until they recover.
- Crawl stats. The Crawl Stats report in Search Console groups responses by status, so a rise in server errors is visible there even if you never saw the error yourself.
Fixing a 500 quickly and making sure it returns an honest status code is the best protection. There is no need to request reindexing of every page once the fault is fixed; crawlers will return to them.
Preventing the next one
- Stage updates. Apply plugin, theme and framework updates to a staging copy first, especially major versions.
- Know your PHP version. Keep track of which PHP version the site runs and when your host plans to retire it, and test the next version on staging before it is forced on you.
- Keep logging on. Leave
log_errorson anddisplay_errorsoff permanently, with log rotation so the files do not fill the disk. - Watch disk space. Old backups and unrotated logs are a common reason for a whole site suddenly returning 500.
- Monitor more than the homepage. A check that only fetches the homepage misses a broken product or checkout template. Include one URL from each important template, and re-run the HTTP Error Audit after each release.
1. What causes a 500 Internal Server Error?
A 500 means the software building the page failed and the server has no more specific code to send. On small business sites the usual causes are a PHP fatal error from a plugin, theme or hand edit, a script running out of memory, an invalid line in .htaccess, a rewrite rule that loops, a lost database connection, or a full disk. The exact reason is almost always written in the web server, PHP or application error log for the time of the request.
2. Where do I find the error log for a 500 error?
Check the web server error log first, such as /var/log/nginx/error.log or the Apache error log, then the PHP-FPM log, then wherever the PHP error_log setting points, then the application log. On shared or managed hosting the control panel usually has a per-domain log view. If you are unsure where PHP logs, a temporary phpinfo page shows the error_log setting, but delete that page immediately afterwards because it exposes server details.
3. Why does my site show a 500 error after updating a plugin or PHP?
Updates change the code or the environment it runs in. A new plugin version may need a newer PHP version or an extension your server lacks, and a newer PHP version removes functions that older plugins and themes still call. The log will show a fatal error naming the file involved. Roll back the plugin or switch PHP back temporarily if your host allows it, then update or replace the incompatible code properly.
4. Can a .htaccess file cause a 500 error?
Yes, and it is one of the most common causes on Apache hosting. A mistyped directive, a module that is not enabled, a php_value line on a server where PHP does not run as an Apache module, or a rewrite rule that keeps matching itself will all produce a 500 for every request the file covers. Temporarily renaming the file and reloading the page is a quick test, but restore it promptly because it also holds your redirects.
5. Should I just increase the PHP memory limit?
Only after you know why the memory is needed. If the log says the allowed memory size was exhausted, a modest increase can be reasonable for a genuinely heavy task such as an import or image processing. If a normal page needs a very large amount, something is wrong, such as a query loading an entire table or a loop that never ends, and raising the limit only delays the failure while making the server slower for everyone.
6. Do 500 errors hurt my Google rankings?
A brief outage is unlikely to have a lasting effect, because search engines expect occasional failures and retry. Repeated or long-running server errors are more serious. Google slows its crawling of a site that keeps returning them, and URLs that fail for an extended period can drop out of the index until they recover. Fix the underlying fault promptly, and for planned downtime use a 503 with a Retry-After header rather than letting pages return 500.
7. Why does the 500 error only happen sometimes?
Intermittent 500s usually come from limits that are only reached under load or at certain times. Examples are memory or worker limits hit when several heavy requests arrive together, database connection limits during a busy period, a backup or scheduled task competing for resources, or an external service the page depends on failing now and then. Match the times in the audit to the logs, and look at what else the server was doing at those moments.
The HTTP Error Audit requests every URL in your crawl scope, records the status code and response time, follows redirects and flags anything outside the 200 range, so you can see which templates fail and when.
Open HTTP Error Fixes โ