HTTP 500 Internal Server Error: A Field Guide to Fixing It
The page went out at 3:12am: error rate on the main site jumped from 0.01% to 40% in ninety seconds. Nothing had deployed in hours. The 500 status code was everywhere in the dashboards and nowhere in the details — because that's what a 500 is. It's the server saying "something went wrong on my end" while deliberately telling you nothing else. The real story that night was a log partition that had filled up, which meant the app couldn't write sessions, which meant every request that touched a session threw an exception. The fix took four minutes. Finding it took forty, because a 500 never points at its own cause.
That's the core skill with this error: knowing that the status code is just the cover page, and the actual report is in a log file somewhere.
The 500 status code is a confession, not a diagnosis
By definition, 500 Internal Server Error means the server hit an unexpected condition that stopped it from fulfilling the request. The word doing the work is unexpected. A 500 is the catch-all that fires when nothing more specific applies — the application threw an unhandled exception, the runtime crashed mid-request, a config file was unparseable. Frameworks return it as the default when your code raises something nobody caught.
Deliberately vague error pages are also a security choice: you don't want a public page printing stack traces, file paths, and database credentials to strangers. So the detail gets written server-side and the visitor gets a shrug. Your job is to go read the detail.
First five minutes: where to look
- Establish scope. Is it every page or one route? Every user or one? A single URL throwing 500s is application logic; the whole site throwing them is infrastructure or a bad deploy. One curl tells you a lot:
curl -sI https://yoursite.com/ | head -1against a few different URLs. - Ask what changed. Most 500 storms start within minutes of a deploy, a dependency update, a config change, or a certificate rotation. If something shipped recently, suspect it first and roll it back before investigating politely.
- Read the application error log. Not the access log — the error log. For a PHP stack that's typically
/var/log/php-fpm/error.log; for anything behind nginx,/var/log/nginx/error.logcatches what the proxy saw. The stack trace with a timestamp matching the incident is your answer nine times out of ten. - Check resources.
df -hfor full disks, memory pressure for OOM kills, database connection counts against their limit. Resource exhaustion is the classic cause of 500s that appear "out of nowhere" with no deploy.
The usual suspects behind HTTP 500
- Unhandled exceptions — a null reference, a type error on unexpected input, an edge case in code that worked fine for two years until someone submitted an emoji in a form field.
- Bad deploys — missing dependencies, environment variables that exist in staging but not production, a migration that ran halfway.
- Resource exhaustion — full disks (logs and temp files are the usual culprits), exhausted database connection pools, hitting file descriptor limits.
- Broken configuration — a syntax error in
.htaccesswill 500 an entire Apache site; a typo'd nginx include does the same. Config errors have the special property of breaking everything at once. - Permission problems — the app can't read a file or write a directory it needs, often after a well-intentioned
chownduring maintenance. - Dependency failures surfacing badly — the database or an internal API went down and the application, lacking any handling for that, converts the failure into an exception and a 500. Strictly speaking the honest code here would be a 502 or 503, but unhandled failures default to 500.
Reading the error log like it's evidence
When you find the stack trace, read it bottom-up: the deepest frame is where the code died, the frames above it tell you how it got there. Correlate the timestamp against your access log to identify which request triggered it — the URL, the method, the payload size. If the same trace repeats thousands of times, you have one bug being hit repeatedly. If you have a dozen different traces, the app isn't buggy; something underneath it (database, disk, memory) is failing and every code path is tripping over it in its own way.
No trace at all? Then the request may be dying before your application sees it — check the web server's own error log, and check whether the worker processes are being killed by the kernel OOM killer (dmesg | grep -i kill is the fastest way to find out).
What sustained 500s do to your search rankings
Google's crawler treats 500s as a sign of server distress, and it reacts in stages. First it slows down: crawl rate drops so Googlebot doesn't add load to a struggling server. Then it stops trusting: pages that consistently return 500 get recrawled less often, and their indexed copies go stale. Finally, if the errors persist for an extended stretch — think weeks, not hours — those URLs start dropping out of the index entirely. A short outage costs you nothing; Google expects servers to have bad days. A long one costs you rankings that take real time to rebuild.
The 500s that hurt most are the ones you don't know about: a template error on one product category, an exception on a paginated archive past page 10. Those can serve errors to crawlers for months while the homepage looks perfect. Scan your whole site for error pages regularly so partial failures surface before they show up as lost traffic in your analytics.
Hardening against the next one
You can't prevent every 500 — unexpected conditions are, by definition, going to happen. What you can control is blast radius and detection time. Alert on error rate, not error existence, so one flaky request doesn't page you but a 2% error rate does. Keep disk usage and connection pool saturation on dashboards, because they're the two resources whose exhaustion most often masquerades as sudden application failure. Make rollbacks one command, since most 500 storms are deploy-shaped and the fastest fix is going back. And keep an eye on baseline performance — a server drifting toward saturation throws sporadic 500s under load spikes long before it fails completely, which is the kind of pattern you catch by watching server response time trends rather than waiting for the pager.
Frequently Asked Questions
Is a 500 error my fault as the site owner or my host's fault?
Statistically it's usually something in your stack — application code, a plugin, a config file, or a resource your site exhausted. It's genuinely the host's problem when their infrastructure (shared database servers, storage, PHP runtime) fails. Check your own error logs first; if they're clean and the timing matches a host-side incident page, escalate to them.
Why does my site show a 500 error only on some pages?
Because the exception lives in code that only those pages execute — a specific template, a query that only certain URLs trigger, or a plugin that only loads in one section. Partial 500s are actually good diagnostic news: whatever those failing pages share that working pages don't is very likely your cause.
How quickly will Google penalize my site for 500 errors?
There's no penalty in the manual-action sense, and an outage of hours has no lasting effect. Google slows crawling within a day or two of persistent 500s, and pages typically only start dropping from the index after errors persist for several weeks. Fix it within days and your search presence recovers essentially unharmed.
Can a full disk really cause 500 errors?
It's one of the most common causes of 500s that appear without any code change. Applications need to write sessions, caches, temp files, and logs; when the disk is full every one of those writes throws an exception. Run df -h during any mystery 500 incident — it takes two seconds and rules out the classic culprit.
Try WebsiteChecker.Tech Free
Run a free technical SEO audit on any website. Get a client-ready report in minutes.
Start Free Scan