Common causes
- A PHP fatal error such as an undefined function, a syntax error or an exhausted memory_limit with display_errors turned off
- An invalid or unsupported directive in .htaccess, for example a module that is not loaded or php_value under PHP-FPM
- A rewrite rule that loops until Apache hits its internal redirect limit (AH00124)
- Scripts or directories that are world-writable or owned by the wrong user, which suEXEC and PHP-FPM setups refuse to run
- A plugin, theme or Composer update that requires a newer PHP version than the server runs
- The application cannot connect to its database or cache and throws an uncaught exception
How to fix it
- Read the error log first. Check /var/log/apache2/error.log, /var/log/httpd/error_log or /var/log/nginx/error.log, plus the PHP-FPM log (for example /var/log/php8.3-fpm.log). On shared hosting use the Errors section in cPanel or the error_log file in the site folder.
- Rule out .htaccess. Rename .htaccess to .htaccess.bak and reload the page. If the 500 disappears, restore the file and remove directives one block at a time until you find the bad line.
- Turn on PHP error logging. Set log_errors = On and error_log = /path/to/php-error.log in php.ini or .user.ini, keeping display_errors = Off on production. In WordPress set WP_DEBUG and WP_DEBUG_LOG to true and read wp-content/debug.log.
- Fix permissions and ownership. Use 755 for directories and 644 for files, with the site owned by the account PHP runs as. Run find /var/www/site -type d -exec chmod 755 {} + and find /var/www/site -type f -exec chmod 644 {} +.
- Disable the last change. If the error started after an update, roll it back or disable the plugin or theme by renaming its folder (for example wp-content/plugins/plugin-name to plugin-name.off).
- Check PHP version and limits. Compare the PHP version with what the code requires (php -v, composer.json require.php). Raise memory_limit or max_execution_time only if the log shows those limits being hit.
php.ini / .user.ini (production logging)
display_errors = Off
log_errors = On
error_log = /var/www/site/logs/php-error.log
error_reporting = E_ALL How to stop it happening again
- Keep PHP error logging permanently on and monitor the log after each deploy
- Test updates on a staging copy that runs the same PHP version as production
- Validate .htaccess changes before uploading them
- Pin dependency versions and check their PHP requirements before upgrading