HTTP
408 - Request Timeout
Getting a 408 Request Timeout means the server stopped waiting for your request—the client took too long to send the complete request body, network latency delayed transmission, or the server's timeout is too aggressive. This client-side error (4xx) happens when the server closes the connection because the request headers or body didn't arrive within the allowed window. Most common during large file uploads without proper streaming, but also appears when slow network connections, client-side processing delays, or aggressive server timeout configurations cut requests short.
#Common Causes
- →Frontend: Large file uploads sent as single request without chunking or streaming. Client-side processing delays (image compression, data transformation) before sending. Slow network connections (mobile, weak WiFi) delay request transmission. Browser connection limits cause queuing delays.
- →Backend: Server timeout configured too short for large payloads. Request body parser (express.json()) times out before receiving full body. Database connection pool exhaustion delays request processing start. Application code blocks during request reception.
- →Infrastructure: Nginx proxy_read_timeout too short for slow clients. Load balancer idle timeout closes connection before request completes. Reverse proxy buffers full, drops connection. Network latency between client and server exceeds timeout window.
✓Solutions
- 1Step 1: Diagnose - Check DevTools Network tab Timing section—look for "stalled" or long "TTFB" times. Verify if request was cancelled mid-transmission. Check browser console for timeout errors.
- 2Step 2: Diagnose - Check server logs for timeout errors (tail -f /var/log/nginx/error.log). Look for "upstream timed out" or "client body timed out" messages. Review server timeout configuration values.
- 3Step 3: Fix - Client-side: Implement chunked uploads for large files (split into 5MB chunks). Use AbortController with appropriate timeout. Stream request body instead of buffering entire payload.
- 4Step 4: Fix - Server-side: Increase timeout settings (req.setTimeout(60000) for 60 seconds). Configure body parser with longer timeout. Use streaming body parsers for large uploads. Implement request queuing for slow clients.
- 5Step 5: Fix - Infrastructure: Increase Nginx proxy_read_timeout and client_body_timeout (e.g., 120s). Configure load balancer idle timeout higher than server timeout. Enable connection keep-alive. Review reverse proxy buffering settings.
</>Code Examples
Fetch API: Client-Side Timeout Handling
1// Client-side: Handle timeout with AbortController
2const controller = new AbortController();
3const timeoutId = setTimeout(() => controller.abort(), 60000); // 60 seconds
4
5fetch('/api/upload', {
6 method: 'POST',
7 body: formData,
8 signal: controller.signal
9})
10.then(response => {
11 clearTimeout(timeoutId);
12 if (!response.ok) {
13 throw new Error(`Upload failed: ${response.status}`);
14 }
15 return response.json();
16})
17.catch(error => {
18 clearTimeout(timeoutId);
19 if (error.name === 'AbortError') {
20 console.error('Request timeout after 60 seconds');
21 showNotification('Upload timed out. Please try again.', 'error');
22 } else {
23 console.error('Upload error:', error);
24 }
25});
26
27// Chunked upload to avoid timeout
28async function uploadLargeFile(file) {
29 const chunkSize = 5 * 1024 * 1024; // 5MB chunks
30 const chunks = Math.ceil(file.size / chunkSize);
31
32 for (let i = 0; i < chunks; i++) {
33 const start = i * chunkSize;
34 const end = Math.min(start + chunkSize, file.size);
35 const chunk = file.slice(start, end);
36
37 await fetch('/api/upload-chunk', {
38 method: 'POST',
39 headers: {
40 'Content-Range': `bytes ${start}-${end - 1}/${file.size}`,
41 'X-Chunk-Index': i.toString(),
42 },
43 body: chunk,
44 });
45 }
46}Express.js: Server-Side Timeout Configuration
1// Server-side: Configure timeouts for large requests
2const express = require('express');
3const app = express();
4
5// Increase timeout for request body reception
6app.use(express.json({
7 limit: '50mb',
8 extended: true
9}));
10
11// Set request timeout (in milliseconds)
12app.use((req, res, next) => {
13 req.setTimeout(120000); // 2 minutes for slow clients
14 res.setTimeout(120000);
15 next();
16});
17
18// Handle timeout errors
19app.use('/api/upload', (req, res, next) => {
20 req.on('timeout', () => {
21 res.status(408).json({
22 error: 'Request Timeout',
23 message: 'Request body took too long to receive'
24 });
25 });
26 next();
27});
28
29// Streaming upload handler to avoid buffering delays
30const multer = require('multer');
31const upload = multer({
32 storage: multer.memoryStorage(),
33 limits: { fileSize: 100 * 1024 * 1024 } // 100MB
34});
35
36app.post('/api/upload', upload.single('file'), (req, res) => {
37 // Process uploaded file
38 res.json({ success: true, filename: req.file.originalname });
39});Nginx: Increase Timeout Settings
1# Nginx: Configure timeouts for slow clients and large uploads
2server {
3 listen 80;
4 server_name api.example.com;
5
6 # Increase timeouts for slow clients
7 client_body_timeout 120s; # Time to read client body
8 client_header_timeout 60s; # Time to read client headers
9 keepalive_timeout 75s; # Keep-alive timeout
10
11 location /api/ {
12 proxy_pass http://backend;
13
14 # Proxy timeouts (must be > client timeouts)
15 proxy_connect_timeout 60s;
16 proxy_send_timeout 120s; # Time to send request to backend
17 proxy_read_timeout 120s; # Time to read response from backend
18
19 proxy_set_header Host $host;
20 proxy_set_header X-Real-IP $remote_addr;
21
22 # Increase buffer sizes for large requests
23 proxy_request_buffering on;
24 client_max_body_size 100m;
25 client_body_buffer_size 1m;
26 }
27}↗Related Errors
Provider Information
This error code is specific to HTTP services. For more information, refer to the official HTTP documentation.