HTTP 500 Internal Server Error: Causes & Fix (nginx, Apache)
Key takeaway
HTTP 500 Internal Server Error means the server "encountered an unexpected condition that prevented it from fulfilling the request" (RFC 9110): something broke on the server, and it didn't say what. As a visitor, reload once after a minute and check whether the site is down for everyone; the fix is the owner's. As the owner, read the error log first. On nginx the 500 usually comes from the app behind it (PHP, Node, Python); on Apache, check .htaccess, PHP limits and plugins.
Check it now

Start reading
- What Is HTTP Error 500?
- What a 500 Error Looks Like
- 500 Internal Server Error on nginx
- Common Causes of HTTP Error 500
- How to Fix a 500 Error (As a Visitor)
- Fix 1: Check Server Error Logs
- Fix 2: Test and Repair .htaccess
- Fix 3: Fix File Permissions
- Fix 4: Increase PHP Memory and Execution Limits
- Fix 5: Disable Plugins and Theme (CMS)
- Fix 6: Check Database Connection and Repair
- Fix 7: Check PHP Version Compatibility
- Fix 8: Check Disk Space
- 500 vs 502 vs 503 vs 504: What's the Difference?
- How 500 Errors Affect SEO
- How to Prevent 500 Errors
- Frequently Asked Questions
What Is HTTP Error 500?
HTTP error 500 (Internal Server Error) means something broke on the web server while it was handling your request, and the server didn't say what. It's the most generic server error.
The HTTP standard defines it in one sentence: "The 500 (Internal Server Error) status code indicates that the server encountered an unexpected condition that prevented it from fulfilling the request" (RFC 9110 §15.6.1). Unlike a 503, it says nothing about whether the problem is temporary.
It's almost always a bug, a bad configuration or a crash in the server-side code, not anything the visitor did. The fix has to come from the site's owner or administrator.
See the status code a page returns
What a 500 Error Looks Like
The wording depends on the server and the app:
- 500 Internal Server Error — the standard status line
- 500 Internal Server Error with "nginx" underneath — nginx's own error page
- The server encountered an internal error or misconfiguration and was unable to complete your request. — Apache's default page
- There has been a critical error on this website. — WordPress's fatal-error page
- HTTP Error 500.19 - Internal Server Error — IIS, where the number after the dot is the reason (500.19: bad configuration data)
- This page isn't working · HTTP ERROR 500 — Chrome, when the 500 response has no page of its own
- Request failed with status code 500 — Axios and other JavaScript code calling an API
- 500. That's an error. — Google's own error page
500 Internal Server Error on nginx
Most of the time nginx is only passing on a 500 that the app behind it returned (PHP-FPM, Node.js, Python); for PHP-FPM, PHP's own error message lands in nginx's log. nginx also makes its own 500 in a few cases. The error log lines to look for:
| nginx error log line | What it means |
|---|---|
| FastCGI sent in stderr: "PHP message: PHP Fatal error: …" | PHP crashed; the message names the file and line (PHP-FPM's errors land in nginx's log) |
| rewrite or internal redirection cycle while internally redirecting to … | try_files or rewrite rules loop back on themselves inside nginx, often a fallback such as /index.html that doesn't exist (a loop the browser follows shows ERR_TOO_MANY_REDIRECTS instead) |
| open() "/etc/nginx/.htpasswd" failed (13: Permission denied) | nginx can't read the auth_basic password file (a missing file gives 403 instead) |
| pwritev() "/var/lib/nginx/body/…" failed (28: No space left on device) | nginx couldn't buffer an upload or large POST to disk: a full disk or a temp folder it can't write |
| (nothing for that request) | A Node.js or Python app returned the 500 and nginx passed it on: read that app's own log |
# What did nginx log?
sudo tail -n 50 /var/log/nginx/error.log
# Look for loops in the loaded config
sudo nginx -T | grep -nE 'try_files|rewrite'(Source: nginx's own code; a crashed or overloaded backend gives 502 or 504, not 500.)
Common Causes of HTTP Error 500
A 500 can come from dozens of server-side problems. The common ones:
- A broken .htaccess file — one invalid directive or a bad RewriteRule makes Apache answer 500 for that directory and everything below it.
- PHP fatal errors — syntax errors, uncaught exceptions or calls to undefined functions stop the script.
- PHP memory or time limits — a script that goes past
memory_limit(128M by default) ormax_execution_time(30 seconds) is stopped. php_valuelines on a PHP-FPM server — they only work with Apache's mod_php; under PHP-FPM, Apache rejects them with a 500.- Wrong file permissions — PHP can't read a file it includes, or a suPHP/suEXEC host refuses files that are writable by everyone (777). (A file the web server itself can't read gives 403.)
- A plugin or theme — a new or updated WordPress, Joomla or Drupal extension that crashes the whole site.
- Database connection failures — wrong credentials, a stopped database server or too many connections.
- Corrupted core files — after a failed update or an interrupted upload.
- A full disk — the server can't write logs, sessions or temporary files.
- nginx's own triggers — a rewrite loop, an unreadable password file, or a temp-file write that fails (often a full disk); see the nginx section above.
How to Fix a 500 Error (As a Visitor)
If you see a 500 error on someone else's website, the problem is on the server side — not yours. However, there are a few things you can try before giving up.
- Reload once after a minute (F5, or Cmd+R on a Mac). Many 500s last only as long as a deploy or a restart.
- Check whether it's down for everyone — the Website Down Checker opens the page from 11 places, and the HTTP Header Checker shows the exact status code our server gets.
- Delete the site's cookies, or try a private window. A broken session cookie can make some apps fail on every page for you alone.
- Try again later — the fix is on the server, so give the owner time.
- Tell the website owner if it lasts for hours, with the page address and the time it happened.
Fix 1: Check Server Error Logs
Error logs are the single most important debugging tool for 500 errors. They tell you exactly what went wrong, including the file path, line number, and error message. Always check logs first before trying anything else.
# Apache (PHP errors appear here too, as "AH01071: Got error 'PHP message: …'")
sudo tail -n 100 /var/log/apache2/error.log # Debian/Ubuntu
sudo tail -n 100 /var/log/httpd/error_log # RHEL/Alma/Rocky
# nginx (PHP errors appear here as "FastCGI sent in stderr")
sudo tail -n 100 /var/log/nginx/error.log
# PHP errors on RHEL-family PHP-FPM
sudo tail -n 100 /var/log/php-fpm/www-error.log
# PHP-FPM process log (pool restarts, pm.max_children)
sudo tail -n 100 /var/log/php8.3-fpm.log # Debian/Ubuntu
# WordPress debug log (with WP_DEBUG_LOG on)
tail -n 100 /path/to/wordpress/wp-content/debug.logFix 2: Test and Repair .htaccess
A broken .htaccess file is a classic cause of 500 errors on Apache: one typo, a directive the server doesn't support, or a bad RewriteRule takes down the directory. Apache's error log names the .htaccess file and the bad directive, for example Invalid command 'php_value', perhaps misspelled or defined by a module not included in the server configuration.
The quickest test is to temporarily rename the file. If the site loads after renaming it, the .htaccess was the problem.
# Rename to disable .htaccess
mv .htaccess .htaccess_backup
# If site loads, regenerate a clean .htaccess
# For WordPress, go to Settings > Permalinks and click SaveFix 3: Fix File Permissions
Permissions cause a 500 when PHP can't read a file it includes, or on suPHP/suEXEC hosts that refuse files writable by everyone. The usual settings are 644 for files and 755 for folders. Never use 777: it's a security risk, and on suEXEC/suPHP hosts it causes a 500 by itself.
# Set correct directory permissions
find /path/to/webroot -type d -exec chmod 755 {} \;
# Set correct file permissions
find /path/to/webroot -type f -exec chmod 644 {} \;
# WordPress wp-config.php (extra security; 440 only if the PHP user owns the file or is in its group)
chmod 440 wp-config.phpFix 4: Increase PHP Memory and Execution Limits
PHP stops scripts that go past the memory limit or the maximum execution time, and the visitor gets a 500. The defaults, 128M of memory and 30 seconds, are often too low for heavy pages.
Raise them where your server reads them. For PHP-FPM, edit the FPM php.ini (for example /etc/php/8.3/fpm/php.ini) and reload php-fpm; .user.ini changes can take up to 5 minutes to apply.
# Option 1: php.ini (best)
memory_limit = 256M
max_execution_time = 300
# Option 2: .htaccess (Apache with mod_php only; under PHP-FPM these lines cause a 500)
php_value memory_limit 256M
php_value max_execution_time 300
# Option 3: .user.ini (PHP-FPM and other FastCGI setups)
memory_limit = 256M
# Option 4: wp-config.php (WordPress)
define( 'WP_MEMORY_LIMIT', '256M' );Fix 5: Disable Plugins and Theme (CMS)
If you are running WordPress, Joomla, or another CMS, a faulty plugin or theme is one of the most common causes of 500 errors. The fastest way to test is to disable all plugins at once, then re-enable them one by one.
# Disable all WordPress plugins (via the file system)
cd /path/to/wordpress/wp-content
mv plugins plugins_disabled
# Or with WP-CLI, without loading the plugin that crashes the site
wp plugin deactivate --all --skip-plugins --skip-themes
# Switch to a default theme (installs it if it was deleted)
wp theme install twentytwentyfive --activate --skip-plugins --skip-themes
# Check WordPress's own files, and reinstall them without touching wp-content
wp core verify-checksums
wp core download --skip-content --forceFix 6: Check Database Connection and Repair
A 500 error can occur when the application cannot connect to its database. This happens when credentials are wrong, the database server is down, or tables are corrupted.
First verify your database credentials in your config file (wp-config.php for WordPress, .env for Laravel). Then test the connection and repair corrupted tables if needed.
# Test the MySQL connection
mysql -u username -p -h localhost database_name -e "SELECT 1;"
# Check tables (REPAIR only fixes MyISAM/Aria tables; for InnoDB, restore from a backup)
mysqlcheck -u username -p --check --auto-repair database_name
# WordPress: add to wp-config.php, then visit /wp-admin/maint/repair.php
# Remove this line when you're done: the repair page needs no login.
define( 'WP_ALLOW_REPAIR', true );Fix 7: Check PHP Version Compatibility
Code written for an older PHP version can hit fatal errors on a newer one (or the reverse). After a PHP upgrade, functions that were removed and behaviour that changed are the usual culprits; deprecated functions only raise notices.
Check which PHP version your site actually runs. php -v on the command line can show a different PHP from the one your site uses, so look in your hosting panel or a temporary phpinfo() page too:
# Command-line PHP (may differ from the site's PHP-FPM)
php -v
# PHP-FPM versions installed (Debian/Ubuntu)
ls /etc/php/
# Modules loaded in the command-line PHP
php -mFix 8: Check Disk Space
When a server runs out of disk space (or inodes), it can't write logs, temporary files or session data, and requests start failing with 500s.
# Check disk space, and inodes (they can run out too)
df -h
df -i
# What's using the space?
sudo du -sh /var/log /tmp
# Free space without deleting the log you're reading
sudo find /var/log -name "*.gz" -mtime +14 -delete
sudo journalctl --vacuum-size=200M500 vs 502 vs 503 vs 504: What's the Difference?
The key distinction: 500 = the server broke internally. 502 = the proxy got garbage back from the backend. 503 = the server is alive but busy. 504 = the proxy gave up waiting. You can check the exact status code your server returns using DNS Robot's HTTP Header Checker.
When the error is a 502 instead, the application may be fine and the problem sits between the proxy and the app. Our 502 Bad Gateway guide covers that case.
| Code | Name | What It Means | Common Cause |
|---|---|---|---|
| 500 | Internal Server Error | The server or app hit an unexpected error, such as an unhandled exception or a bad config | PHP fatal error, bad .htaccess, memory exhaustion |
| 502 | Bad Gateway | A proxy received an invalid response from the backend | PHP-FPM crashed, backend not running, socket closed |
| 503 | Service Unavailable | Server is temporarily overloaded or in maintenance | Traffic spike, planned maintenance, resource limits |
| 504 | Gateway Timeout | A proxy timed out waiting for the backend to respond | Slow database query, long-running script, unresponsive upstream |
How 500 Errors Affect SEO
Google's own documentation describes what happens (Google crawler docs):
- Crawling slows down. On 5xx errors Google reduces the crawl rate for the site, in proportion to the number of URLs returning errors.
- Indexed pages stay at first. Already indexed URLs are kept for a while, but URLs that persistently return a server error are removed.
- Recovery is gradual. Once the server answers with 2xx again, Google gradually increases crawling.
- Use 503 for planned downtime of a day or two, with a Retry-After header (Google), so the downtime reads as temporary (503 guide).
How to Prevent 500 Errors
Prevention is always better than debugging. Follow these best practices to minimize the risk of 500 errors on your website.
- Set up uptime monitoring — Use tools like UptimeRobot or Pingdom to check your site every 1-5 minutes. Get instant alerts when a 500 error occurs.
- Always test changes in staging — Never deploy directly to production. Test plugin updates, PHP upgrades, and config changes in a staging environment first.
- Use version control (Git) — Commit every change so you can instantly revert a bad deploy with a single command.
- Implement proper error handling — Wrap database queries and API calls in try-catch blocks. Log full stack traces server-side for every error.
- Monitor disk space and server resources — Set up alerts for disk usage above 80%, high CPU, and memory pressure.
- Keep software updated — Outdated CMS versions, plugins, and server software contain known bugs that cause crashes.
- Maintain automated backups — Test your restore procedure regularly. A backup you have never tested is not a backup.
- Set PHP limits appropriately — Configure memory_limit and max_execution_time based on your actual workload, not default values.
- Use CI/CD pipelines — Automate testing before deployment. If tests fail, the deploy should not proceed.
See the status code a page returns
DNS Robot's free HTTP Header Checker requests any URL from our server and shows the exact status code and response headers, so you can confirm a 500 and see which server sent it.
Sources
Frequently Asked Questions
What does HTTP error 500 mean?
How does RFC 9110 define 500 Internal Server Error?
How do I fix a 500 internal server error?
Is a 500 error my fault as a visitor?
What does 500 Internal Server Error nginx mean?
What is the difference between a 500 and 503 error?
Can a 500 error affect my Google rankings?
What causes a 500 error in WordPress?
What does "Request failed with status code 500" mean?
Why do I get a 500 error on only some pages?
Related Articles
Related Tools
HTTP Header Checker
Response headers exactly as sent, with a Mozilla Observatory security grade
Website Down Checker
Is it down for everyone or just you? Check any site from 11 places and your own connection, with a live screenshot
Redirect Checker
Follow every redirect hop by hop: 301/302 chains, timing and bulk checks
DNS Lookup
Every DNS record from the domain's own nameservers, beside Google's and Cloudflare's cache



