The site is returning 500. It's not a white screen, nor a clear message; just a dry, unexplained Internal Server Error. The first thing you do is go to the server error log. And this is where most people waste the first ten minutes, because they don't know which file to open and what to look for.
This article follows exactly that path: where the logs are, how to find a specific request among thousands of lines, and why error_log and access_log are two completely different things that you shouldn't mix up.
Where the server error log is and why you can't find it
On Linux shared hosting, logs are usually in your account's home directory, not in /var/log. If you've logged in via SSH, run this first:
ls -la ~/logs/ ~/public_html/error_log 2>/dev/null
In cPanel and DirectAdmin, the main file is usually ~/logs/error_log or ~/public_html/error_log. If neither exists, ask the web server itself:
apachectl -S 2>/dev/null | head -20
php -i | grep -i error_log
The last line of the php -i output shows the actual path of error_log at the PHP level. Write this down; half of all confusion comes from the fact that the Apache log and the PHP log are written to two separate files and you're only looking at one of them.
On a dedicated server or VPS, the paths are different. Apache on Debian and Ubuntu writes to /var/log/apache2/error.log, on CentOS and AlmaLinux to /var/log/httpd/error_log. If Nginx sits in front of PHP-FPM, PHP errors go to /var/log/php-fpm/www-error.log and the Nginx log only keeps web-layer errors. That means a single 500 error can leave traces in three different files.
The difference between error_log and access_log at a glance
Memorize this table once and for all, because most of the time people spend hours reading access_log looking for errors:
| Feature | error_log | access_log |
|---|---|---|
| What is recorded | Errors, warnings, crashes | Every HTTP request, successful or not |
| Line structure | Free text + error level | Combined format: IP, time, method, path, status code, size |
| Has a status code? | No | Yes, such as 200, 404, 500 |
| What it's for | Understanding the cause of failure | Understanding what happened and how much |
A sample line from access_log:
185.55.12.9 - - [14/Feb/2025:09:41:22 +0330] "POST /cart/checkout HTTP/1.1" 500 312 "-" "Mozilla/5.0"
This line says a user got a 500 error on the path /cart/checkout at 09:41. But it doesn't say why. For the "why," you need to look at that same moment in error_log. Here's where people make a mistake: they see the 500 code in access_log, think they've found the log, and then refresh the page ten times hoping the error message will appear. The error message isn't there. It's in another file.
How to find a specific request in the server error log
Suppose you have that /cart/checkout error and want to know what was behind it. First grab the time range from access_log, then search that range in error_log:
grep "14/Feb/2025:09:4" ~/logs/access_log | grep " 500 "
grep -A 5 "09:41:2" ~/logs/error_log
The -A 5 flag also shows five lines after each match, because a PHP error is usually multi-line and the stack trace comes below the first line. If you only see the first line, you usually won't get anything useful out of it.
When the log file is large, grep on the whole file becomes slow. If the log has been rotated and you have error_log.1 and error_log.2.gz files, search directly on the compressed version:
zgrep -i "fatal error" ~/logs/error_log.2.gz
To watch the log live, when you don't know when the error occurs:
tail -f ~/logs/error_log | grep -v "favicon"
Don't underestimate that grep -v. On high-traffic sites, lines related to favicon.ico and bot requests can fill more than half the output and distract you from the real error.
Reading error levels: what actually matters
In the PHP log, every line starts with a level. You need to distinguish these from each other:
- Fatal error: the script stopped right there. This almost always causes a 500 and should be the first thing you look for.
- Parse error: a syntax error in the code. It usually appears after an edit or an incomplete file upload.
- Warning: the script continued, but something wasn't right. Like
include(): Failed opening. - Notice and Deprecated: they become numerous in newer PHP versions and on their own don't bring the site down.
A real example I see often:
[14-Feb-2025 09:41:22 UTC] PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /home/user/public_html/wp-includes/wp-db.php on line 2056
The number 134217728 is 128 megabytes. That means memory_limit was set to 128M and the script didn't have room. The quick fix is to raise this value in php.ini or .user.ini:
memory_limit = 256M
But there's a trap here that I have to be honest about: raising memory_limit hides the problem, it doesn't solve it. If a plugin consumes 200 megabytes on every request, with 256M it just goes down a little later, and on a high-traffic server it drives up the whole server's memory usage. If the memory error repeats on a specific path, the problem is that plugin or query, not the memory_limit number.
Errors that aren't in the log and where else to look
Sometimes the site returns 500 but error_log is completely empty. This situation has a few specific causes:
- The error occurred at the web server level, not PHP. For example, a broken
.htaccess. In this case, look at the Apache log, not the PHP log. - The error is at the DNS or connection level and never reached your server. For this case, DNS and network lookup is the right starting point.
- Logging is turned off. If both
display_errorsandlog_errorsare off, nothing gets written anywhere.
For the third case, put these two lines in php.ini or .user.ini:
log_errors = On
error_log = /home/user/logs/php_error.log
Then restart the web server. On PHP-FPM, changes to php.ini don't take effect without restarting the service, and that's what makes you think the setting didn't work.
When the error isn't from the code itself
Sometimes the log is full of errors but the site works fine. For example, hundreds of Deprecated: Creation of dynamic property lines in PHP 8.2. These shouldn't be ignored, but they're not the top priority either. Put your priority on Fatal error and 500 codes.
If the site is slow but there's no error in the log, the issue is elsewhere. In that case, the right path is performance troubleshooting, not error troubleshooting; the guide Why is the site slow? A complete guide to troubleshooting a slow site covers exactly that path and starts with TTFB and query time.
One practical tip: before making any change on a live server, set up a separate environment. The guide Setting up a staging environment for your site shows how to reproduce the error without touching the main site. In the long run, this saves you the most time.
Tools that shorten the work
For quickly counting errors by type:
grep -o "PHP Fatal error" ~/logs/error_log | wc -l
awk '{print $5}' ~/logs/access_log | sort | uniq -c | sort -rn | head
The second line counts status codes and shows what percentage of requests were 500s. If the 500 count is high relative to total requests, the problem is no longer just a single user.
If you're on shared hosting and don't have SSH access, you can usually download the logs from the panel. In Linux hosting, these files are viewable and downloadable from the panel itself and don't require root access. For lighter tasks like checking headers and redirects, free webmaster tools respond faster than opening a terminal.
And if the log volume passes a few gigabytes and grep becomes slow on shared hosting, it's time to think about a dedicated server; not because of processing power, but because of control over log rotation and long-term retention.
Frequently asked questions
Where is the server error log on shared hosting?
In most Linux panels, the error_log file is inside the logs folder at the root of your account, meaning a path like ~/logs/error_log. If it's not there, find the exact path with php -i | grep error_log, because the PHP log and the web server log are two separate files.
Why does the site return a 500 error but error_log is empty?
Usually because the error occurred at the web server level, not PHP; for example, an invalid line in .htaccess. Another cause is that log_errors is off and nothing gets written anywhere. In both cases, you need to check the Apache or Nginx log separately.
How do I figure out which request caused the error?
First grab the time and path of the request from access_log, then search that same time range in error_log. The grep -A 5 command on error_log helps you see several lines after the error, because the stack trace is usually multi-line.
Does raising memory_limit solve the problem?
It only moves the symptom around. If a plugin or query consumes a lot of memory on every request, raising memory_limit makes it go down later, not get fixed. Find the root cause in that plugin or query.
The next step is simple: right now, run tail -f on error_log and open the site in your browser. If an error is occurring, it will appear before your eyes at that very moment. If it doesn't appear, then the error is somewhere else and you need to go to the web server log.
Comments 0
No comments yet — be the first!