- Home
- HTTP Status Codes
- HTTP 500 Internal Server Error: Causes and Solutions
Status Code
HTTP 500 Internal Server Error: Causes and Solutions
Learn what HTTP 500 Internal Server Error means, common causes, and how to fix it. Complete troubleshooting guide for developers.
TL;DR: 500 Internal Server Error means something broke on the server. It’s not your fault—wait and retry later.
500 is the generic “something went wrong” error. When a server encounters an unexpected condition and doesn’t know how to handle it, it returns 500. It’s the server’s way of saying “I broke, but I’m not sure why.”
What is a 500 Error?
A 500 error indicates the server failed to fulfill a valid request:
GET /api/users HTTP/1.1
Host: api.example.com
```text
Response:
```http
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": "Internal Server Error",
"message": "An unexpected error occurred"
}
The request was valid, but something on the server broke while processing it.
Common Causes
1. Application Code Errors
Unhandled exceptions, null pointer errors, or bugs:
// Uncaught exception causes 500
app.get('/users/:id', (req, res) => {
const user = getUser(req.params.id)
res.json(user.profile.name) // Crashes if user is null!
})
```text
### 2. Database Connection Failures
```http
Error: Connection refused to database server
Error: Too many connections
Error: Query timeout after 30000ms
```text
### 3. Out of Memory
```http
Error: JavaScript heap out of memory
Fatal error: Allowed memory size exhausted
```text
### 4. File Permission Issues
```http
Error: EACCES: permission denied, open '/var/log/app.log'
Error: Cannot write to /tmp/uploads
```text
### 5. Configuration Errors
```http
Error: Invalid JSON in config.json
Error: Missing required environment variable DATABASE_URL
```text
### 6. Third-Party Service Failures
```http
Error: Payment gateway timeout
Error: Email service unavailable
```text
### 7. Disk Space Exhaustion
```http
Error: No space left on device
Error: Cannot create temporary file
```text
## Example Responses
### Generic Error (Production)
```http
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": "Internal Server Error",
"message": "Something went wrong. Please try again later.",
"requestId": "req-abc-123"
}
Detailed Error (Development Only)
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": "TypeError",
"message": "Cannot read property 'name' of undefined",
"stack": "TypeError: Cannot read property 'name' of undefined\n at /app/routes/users.js:42:15",
"requestId": "req-abc-123"
}
```text
⚠️ Never expose stack traces in production!
### HTML Error Page
```http
HTTP/1.1 500 Internal Server Error
Content-Type: text/html
<!DOCTYPE html>
<html>
<head><title>Server Error</title></head>
<body>
<h1>500 - Internal Server Error</h1>
<p>We're experiencing technical difficulties. Please try again later.</p>
<p>Error ID: req-abc-123</p>
</body>
</html>
Troubleshooting Guide
Step 1: Check Server Logs
# Application logs
tail -f /var/log/app/error.log
# Web server logs
tail -f /var/log/nginx/error.log
# System logs
journalctl -u myapp -f
```text
Look for:
- Stack traces
- Error messages
- Timestamps correlating with 500 errors
### Step 2: Check Resource Usage
```bash
# Memory
free -m
# Disk space
df -h
# CPU and processes
top
# Database connections
mysql -e "SHOW STATUS LIKE 'Threads_connected';"
Step 3: Review Recent Changes
- Recent deployments
- Configuration changes
- Database migrations
- Dependency updates
Step 4: Test in Isolation
# Test database connection
mysql -u user -p -h localhost database
# Test API endpoint directly
curl -v http://localhost:3000/api/health
# Check environment variables
printenv | grep DATABASE
```text
### Step 5: Check Dependencies
```bash
# External services
curl -I https://api.stripe.com/v1/health
curl -I https://api.sendgrid.com/v3/health
# DNS resolution
nslookup api.example.com
Handling 500 Errors
Server-Side Error Handling
// Express.js error handler
app.use((err, req, res, next) => {
// Log full error details
console.error({
error: err.message,
stack: err.stack,
requestId: req.id,
url: req.url,
method: req.method,
timestamp: new Date().toISOString()
})
// Send safe response to client
res.status(500).json({
error: 'Internal Server Error',
message: 'An unexpected error occurred',
requestId: req.id
})
})
```javascript
### Graceful Degradation
```javascript
async function getUser(id) {
try {
return await database.query('SELECT * FROM users WHERE id = ?', [id])
} catch (error) {
// Log error
logger.error('Database query failed', { error, userId: id })
// Try cache fallback
const cached = await cache.get(`user:${id}`)
if (cached) {
return cached
}
// Re-throw if no fallback
throw error
}
}
Client-Side Handling
async function fetchData() {
try {
const response = await fetch('/api/data')
if (response.status === 500) {
// Log for debugging
const errorId = response.headers.get('X-Request-ID')
console.error('Server error:', errorId)
// Show user-friendly message
showError('Something went wrong. Please try again later.')
return null
}
return response.json()
} catch (error) {
showError('Unable to connect to server')
return null
}
}
```javascript
### Retry Logic
```javascript
async function fetchWithRetry(url, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url)
if (response.status === 500 && attempt < maxRetries) {
// Wait before retry (exponential backoff)
await sleep(Math.pow(2, attempt) * 1000)
continue
}
return response
} catch (error) {
if (attempt === maxRetries) throw error
await sleep(Math.pow(2, attempt) * 1000)
}
}
}
500 vs Other 5xx Errors
| Code | Name | Meaning |
|---|---|---|
| 500 | Internal Server Error | Generic server failure |
| 501 | Not Implemented | Server doesn’t support the functionality |
| 502 | Bad Gateway | Invalid response from upstream server |
| 503 | Service Unavailable | Server temporarily overloaded |
| 504 | Gateway Timeout | Upstream server didn’t respond in time |
When to Use Each
# 500: Your code crashed
throw new Error('Unexpected condition')
# 501: Feature not built
if (method === 'PATCH') return 501
# 502: Upstream returned garbage
upstream_response = "<!DOCTYPE html>..." // Expected JSON
# 503: Intentionally unavailable
if (maintenance_mode) return 503
# 504: Upstream too slow
upstream_timeout after 30 seconds
```http
## Best Practices
### Logging
```javascript
// Include context for debugging
logger.error('Request failed', {
error: err.message,
stack: err.stack,
requestId: req.id,
userId: req.user?.id,
url: req.originalUrl,
method: req.method,
body: sanitize(req.body),
headers: sanitize(req.headers),
timestamp: new Date().toISOString()
})
Monitoring
Set up alerts for:
- 500 error rate exceeds threshold
- Error rate spike (sudden increase)
- Specific error patterns
- Resource exhaustion warnings
Error Pages
<!DOCTYPE html>
<html>
<head>
<title>Server Error</title>
<style>
body {
font-family: sans-serif;
text-align: center;
padding: 50px;
}
h1 {
color: #e74c3c;
}
</style>
</head>
<body>
<h1>500 - Server Error</h1>
<p>We're sorry, something went wrong on our end.</p>
<p>Our team has been notified and is working on it.</p>
<p><a href="/">Return to Homepage</a></p>
<p style="color: #999; font-size: 12px;">Error ID: {{requestId}}</p>
</body>
</html>
```text
### Security
```javascript
// ❌ Never expose internal details
res.status(500).json({
error: err.message,
stack: err.stack,
query: 'SELECT * FROM users WHERE...'
})
// ✅ Safe error response
res.status(500).json({
error: 'Internal Server Error',
requestId: req.id // For support reference
})
Prevention Strategies
Input Validation
// Validate before processing
const { error, value } = schema.validate(req.body)
if (error) {
return res.status(400).json({ error: error.message })
}
```javascript
### Defensive Coding
```javascript
// Check for null/undefined
const userName = user?.profile?.name ?? 'Unknown'
// Use try-catch for risky operations
try {
const result = JSON.parse(data)
} catch {
return res.status(400).json({ error: 'Invalid JSON' })
}
Health Checks
app.get('/health', async (req, res) => {
const checks = {
database: await checkDatabase(),
cache: await checkCache(),
disk: checkDiskSpace()
}
const healthy = Object.values(checks).every((c) => c.ok)
res.status(healthy ? 200 : 500).json(checks)
})
```javascript
### Circuit Breakers
```javascript
const breaker = new CircuitBreaker(callExternalService, {
timeout: 3000,
errorThreshold: 50,
resetTimeout: 30000
})
// Fails fast when service is down
const result = await breaker.fire(params)
Try It Yourself
While we can’t intentionally trigger 500 errors in our demo, you can observe error handling in the request builder:
- Try various endpoints
- Observe how errors are formatted
- Check response headers for error tracking IDs
Related Status Codes
- 400 Bad Request - Client sent invalid request
- 502 Bad Gateway - Upstream server error
- 503 Service Unavailable - Temporary overload
- 504 Gateway Timeout - Upstream timeout
Related Concepts
- Error Handling - Handling failures gracefully
- HTTP Methods - Request types
- Status Codes Overview - All status codes
In Practice
Express.js
// Global error handler — must have 4 params
app.use((err, req, res, next) => {
// Log full error server-side
console.error({ err, path: req.path, method: req.method })
// Never expose internals to clients
const status = err.status ?? 500
res.status(status).json({
error: status < 500 ? err.message : 'Internal server error'
})
})
// Async route — wrap with try/catch or use express-async-errors
app.get('/api/data', async (req, res, next) => {
try {
const data = await fetchData()
res.json(data)
} catch (err) {
next(err) // Passes to error handler above
}
})Next.js App Router
// app/api/data/route.ts
export async function GET() {
try {
const data = await fetchData()
return Response.json(data)
} catch (err) {
// Log server-side
console.error('GET /api/data failed:', err)
// Return generic 500 to client
return Response.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
// app/error.tsx — catches render errors in page routesDjango
# Django returns 500 automatically for unhandled exceptions.
# Customize the response in views.py:
import logging
from django.http import JsonResponse
logger = logging.getLogger(__name__)
def api_view(request):
try:
data = fetch_data()
return JsonResponse(data)
except Exception as e:
logger.exception('api_view failed')
return JsonResponse(
{'error': 'Internal server error'},
status=500
)
# settings.py — disable DEBUG in production
# DEBUG = False
# ADMINS = [('Admin', 'admin@example.com')]Frequently Asked Questions
What does 500 Internal Server Error mean?
A 500 error means something went wrong on the server while processing your request. The server encountered an unexpected condition that prevented it from fulfilling the request. It is a generic server-side error.
How do I fix a 500 Internal Server Error?
Check server logs for the actual error message, verify database connections, check file permissions, review recent code changes, ensure sufficient server resources (memory, disk), and check for syntax errors in configuration files.
Is a 500 error my fault as a user?
No, 500 errors are server-side problems. As a user, you can try refreshing the page, clearing your browser cache, or waiting a few minutes. If the error persists, contact the website administrator.
What is the difference between 500 and 502 errors?
500 means the origin server itself failed. 502 Bad Gateway means a proxy or gateway received an invalid response from the upstream server. 500 is the server fault; 502 is a communication problem between servers.
Why do I see 500 errors intermittently?
Intermittent 500 errors often indicate resource exhaustion (memory, connections), race conditions, timeout issues, or load-related problems. Check server metrics during error occurrences to identify patterns.
Should I show 500 error details to users?
Never expose stack traces or internal error details to users in production. This is a security risk. Log detailed errors server-side and show users a friendly generic message with a way to report the issue.