How to Mock 500 Internal Server Error Response (2026)
Test your API error handling with simulated server failures
Start Building with Hypereal
Access Kling, Flux, Sora, Veo & more through a single API. Free credits to start, scale to millions.
No credit card required • 100k+ developers • Enterprise ready
How to Mock 500 Internal Server Error Response in 2026
A 500 Internal Server Error is the generic "something went wrong on the server" HTTP status code. When building APIs or integrating with third-party services, you need to test how your application handles these failures gracefully. The problem is that you cannot easily trigger real 500 errors on demand, so you need to mock them.
This guide walks through every practical method for mocking 500 errors: from simple tools to full programmatic approaches in multiple languages.
Why Mock 500 Errors?
Before writing any code, here is why this matters:
| Scenario | What Happens Without Mocking |
|---|---|
| Third-party API goes down | Your app crashes or hangs |
| Database connection drops | Users see raw error messages |
| Microservice fails | Cascading failures across services |
| Rate limit triggers server error | No retry logic kicks in |
| Deployment issue causes 500s | No fallback UI for users |
If you only test the happy path, your application will break in production when it encounters a 500 response. Mocking lets you build and verify resilient error handling.
Method 1: Use httpstat.us (Instant, No Setup)
The simplest approach. httpstat.us is a free service that returns any HTTP status code you request.
# Get a 500 Internal Server Error response
curl -i https://httpstat.us/500
# Response:
# HTTP/1.1 500 Internal Server Error
# Content-Type: text/plain
# ...
# 500 Internal Server Error
Add a simulated delay to mimic a slow dying server:
# 500 error after a 3-second delay
curl -i "https://httpstat.us/500?sleep=3000"
This works great for quick manual testing, but you cannot customize the response body.
Method 2: Use Mock Server Tools
JSON Server with Custom Routes
Create a mock API that returns 500 errors for specific endpoints:
npm install -g json-server
Create a routes.json file:
{
"/api/unstable": "/error500"
}
Create a middleware file server-error.js:
// server-error.js
module.exports = (req, res, next) => {
if (req.path === '/api/unstable') {
return res.status(500).json({
error: 'Internal Server Error',
message: 'The server encountered an unexpected condition',
timestamp: new Date().toISOString(),
requestId: 'req_' + Math.random().toString(36).substr(2, 9)
});
}
next();
};
Run it:
json-server --watch db.json --middlewares server-error.js --port 3001
MSW (Mock Service Worker) for Frontend Testing
MSW intercepts network requests at the service worker level, making it excellent for frontend testing:
npm install msw --save-dev
// src/mocks/handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
// Mock a 500 error on a specific endpoint
http.get('/api/users', () => {
return HttpResponse.json(
{
error: 'Internal Server Error',
message: 'Database connection failed',
code: 'DB_CONNECTION_ERROR',
},
{ status: 500 }
);
}),
// Mock intermittent 500 errors (50% failure rate)
http.post('/api/orders', () => {
if (Math.random() > 0.5) {
return HttpResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
return HttpResponse.json(
{ id: 'order_123', status: 'created' },
{ status: 201 }
);
}),
];
Set up the mock server in your tests:
// src/mocks/setup.ts
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
// In your test file
import { server } from '../mocks/setup';
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
test('displays error message on 500 response', async () => {
// Your component test here - the API call will return 500
});
Method 3: Mock in Unit Tests
JavaScript/TypeScript with Jest
// api.ts
export async function fetchUsers(): Promise<User[]> {
const response = await fetch('/api/users');
if (!response.ok) {
throw new Error(`Server error: ${response.status}`);
}
return response.json();
}
// api.test.ts
import { fetchUsers } from './api';
// Mock fetch globally
global.fetch = jest.fn();
test('handles 500 error gracefully', async () => {
(global.fetch as jest.Mock).mockResolvedValue({
ok: false,
status: 500,
statusText: 'Internal Server Error',
json: async () => ({
error: 'Internal Server Error',
message: 'Unexpected database failure',
}),
});
await expect(fetchUsers()).rejects.toThrow('Server error: 500');
});
test('retries on 500 error', async () => {
const mockFetch = global.fetch as jest.Mock;
// First call: 500 error
mockFetch.mockResolvedValueOnce({
ok: false,
status: 500,
});
// Second call: success
mockFetch.mockResolvedValueOnce({
ok: true,
status: 200,
json: async () => [{ id: 1, name: 'Alice' }],
});
// Your retry logic should handle this
const users = await fetchUsersWithRetry();
expect(users).toHaveLength(1);
expect(mockFetch).toHaveBeenCalledTimes(2);
});
Python with pytest and responses
import pytest
import requests
import responses
@responses.activate
def test_handles_500_error():
# Mock the endpoint to return 500
responses.add(
responses.GET,
"https://api.example.com/users",
json={
"error": "Internal Server Error",
"message": "Database connection pool exhausted"
},
status=500,
)
# Your function should handle this gracefully
with pytest.raises(requests.exceptions.HTTPError) as exc_info:
response = requests.get("https://api.example.com/users")
response.raise_for_status()
assert exc_info.value.response.status_code == 500
@responses.activate
def test_retry_on_500():
# First request: 500 error
responses.add(
responses.GET,
"https://api.example.com/data",
json={"error": "Internal Server Error"},
status=500,
)
# Second request: success
responses.add(
responses.GET,
"https://api.example.com/data",
json={"data": [1, 2, 3]},
status=200,
)
result = fetch_with_retry("https://api.example.com/data", max_retries=3)
assert result == {"data": [1, 2, 3]}
Python with unittest.mock
from unittest.mock import patch, MagicMock
import requests
def fetch_data(url):
response = requests.get(url)
if response.status_code == 500:
raise RuntimeError("Server error, please retry later")
return response.json()
@patch("requests.get")
def test_500_error_handling(mock_get):
# Configure the mock to return a 500 response
mock_response = MagicMock()
mock_response.status_code = 500
mock_response.json.return_value = {
"error": "Internal Server Error"
}
mock_get.return_value = mock_response
with pytest.raises(RuntimeError, match="Server error"):
fetch_data("https://api.example.com/data")
Method 4: Express.js Mock Server
Create a dedicated mock server that you can configure to return errors:
// mock-server.js
const express = require('express');
const app = express();
app.use(express.json());
// Always returns 500
app.get('/api/always-fail', (req, res) => {
res.status(500).json({
error: 'Internal Server Error',
message: 'This endpoint always fails',
timestamp: new Date().toISOString(),
});
});
// Configurable failure rate
let failureRate = 0.5;
app.post('/api/config/failure-rate', (req, res) => {
failureRate = req.body.rate;
res.json({ failureRate });
});
app.get('/api/flaky', (req, res) => {
if (Math.random() < failureRate) {
return res.status(500).json({
error: 'Internal Server Error',
message: 'Random failure occurred',
});
}
res.json({ data: 'Success', timestamp: new Date().toISOString() });
});
// Delayed 500 (simulates timeout-like behavior)
app.get('/api/slow-fail', (req, res) => {
const delay = parseInt(req.query.delay) || 5000;
setTimeout(() => {
res.status(500).json({
error: 'Internal Server Error',
message: `Failed after ${delay}ms delay`,
});
}, delay);
});
app.listen(3001, () => {
console.log('Mock server running on http://localhost:3001');
});
Run it and test:
node mock-server.js
# Test the always-fail endpoint
curl -i http://localhost:3001/api/always-fail
# Test the flaky endpoint
curl -i http://localhost:3001/api/flaky
# Set failure rate to 100%
curl -X POST http://localhost:3001/api/config/failure-rate \
-H "Content-Type: application/json" \
-d '{"rate": 1.0}'
Method 5: Nginx Configuration for Mock Responses
If you use Nginx as a reverse proxy, you can return 500 errors for specific routes:
server {
listen 8080;
# Return 500 for a specific endpoint
location /api/test-error {
return 500 '{"error": "Internal Server Error", "message": "Mocked by Nginx"}';
add_header Content-Type application/json;
}
# Proxy everything else to your real backend
location / {
proxy_pass http://localhost:3000;
}
}
Building Retry Logic to Handle 500 Errors
Once you can mock 500 errors, you need to write code that handles them. Here is a robust retry pattern:
async function fetchWithRetry(
url: string,
options: RequestInit = {},
maxRetries: number = 3,
baseDelay: number = 1000
): Promise<Response> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url, options);
if (response.status === 500 && attempt < maxRetries) {
// Exponential backoff: 1s, 2s, 4s
const delay = baseDelay * Math.pow(2, attempt);
console.warn(`Attempt ${attempt + 1} failed with 500. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return response;
} catch (error) {
if (attempt === maxRetries) throw error;
const delay = baseDelay * Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error('Max retries exceeded');
}
Wrapping Up
Mocking 500 errors is a fundamental part of building reliable applications. Whether you use a simple service like httpstat.us for quick checks, MSW for frontend tests, or a custom Express mock server for integration testing, the important thing is that your error handling is verified before production.
| Method | Best For | Setup Time |
|---|---|---|
| httpstat.us | Quick manual testing | None |
| MSW | Frontend unit/integration tests | 5 minutes |
| Jest/pytest mocks | Backend unit tests | 2 minutes |
| Express mock server | Integration testing | 10 minutes |
| Nginx config | Staging environment testing | 5 minutes |
If you are building applications that consume AI APIs for image generation, video processing, or other media tasks, robust error handling is especially important since inference endpoints can be unpredictable. Hypereal AI provides reliable API endpoints with clear error responses, built-in rate limiting, and detailed status codes that make error handling straightforward.
Related Articles
Start Building Today
Get 35 free credits on signup. No credit card required. Generate your first image in under 5 minutes.
