HTTP

416 - Range Not Satisfiable

Hitting a 416 Range Not Satisfiable means your Range header requested bytes outside the file's actual size—asking for bytes 1000-2000 on a 500-byte file, or the range format is invalid. This client-side error (4xx) happens when servers validate Range headers for partial content requests. Most common during video streaming or large file downloads where range calculations are wrong, but also appears when file sizes change between requests, range syntax is malformed, or multiple overlapping ranges confuse the server.

#Common Causes

  • Frontend: Range header exceeds file size (requesting bytes beyond Content-Length). Invalid range format (bytes=start-end syntax errors). Range start value greater than end value. Multiple overlapping ranges in single request. Stale file size cached, file was truncated.
  • Backend: File size changed between HEAD and GET requests. Range validation logic rejects valid ranges. Server doesn't support range requests (no Accept-Ranges header). File was deleted or modified during range request.
  • Infrastructure: CDN serves stale Content-Length headers. Load balancer modifies Range headers incorrectly. Reverse proxy doesn't support range requests. File storage system reports wrong file size.

Solutions

  1. 1Step 1: Diagnose - Check DevTools Network tab Response Headers for Content-Length and Accept-Ranges. Verify Range header format (bytes=start-end). Compare requested range against Content-Length value.
  2. 2Step 2: Diagnose - Server logs show which range was requested and file size. Check if file was modified between requests. Review range validation logic. Verify Accept-Ranges header is present.
  3. 3Step 3: Fix - Client-side: Get file size first with HEAD request before sending Range header. Validate range values (start < end, both < Content-Length). Use single range requests (not multiple). Handle 416 by requesting full resource.
  4. 4Step 4: Fix - Server-side: Return Accept-Ranges: bytes header. Validate range syntax before processing. Return 416 with Content-Range header showing actual file size. Support range requests properly (206 Partial Content for valid ranges).
  5. 5Step 5: Fix - Infrastructure: Ensure CDN passes Range headers correctly. Configure load balancer to support range requests. Verify reverse proxy doesn't strip Range headers. Check file storage system reports accurate sizes.

</>Code Examples

Fetch API: Validate Range Before Request
1// Client-side: Handle 416 by validating ranges first
2async function downloadChunk(url, start, end) {
3  // First, get file size with HEAD request
4  const headResponse = await fetch(url, { method: 'HEAD' });
5  const contentLength = parseInt(headResponse.headers.get('Content-Length') || '0');
6  const acceptRanges = headResponse.headers.get('Accept-Ranges');
7  
8  if (acceptRanges !== 'bytes') {
9    throw new Error('Server does not support range requests');
10  }
11  
12  // Validate range
13  if (start < 0 || end < start || start >= contentLength) {
14    throw new Error(`Invalid range: start=${start}, end=${end}, size=${contentLength}`);
15  }
16  
17  // Clamp end to file size
18  const clampedEnd = Math.min(end, contentLength - 1);
19  
20  const response = await fetch(url, {
21    headers: {
22      'Range': `bytes=${start}-${clampedEnd}`,
23    },
24  });
25  
26  if (response.status === 416) {
27    // Range not satisfiable - get full resource
28    console.warn('Range not satisfiable, downloading full resource');
29    return fetch(url);
30  }
31  
32  if (response.status === 206) {
33    // Partial content - valid range
34  return response;
35}
36
37  return response;
38}
39
40// Download file in chunks with proper error handling
41async function downloadFileInChunks(url, chunkSize = 1024 * 1024) {
42const headResponse = await fetch(url, { method: 'HEAD' });
43  const totalSize = parseInt(headResponse.headers.get('Content-Length') || '0');
44  const chunks = [];
45  
46  for (let start = 0; start < totalSize; start += chunkSize) {
47    const end = Math.min(start + chunkSize - 1, totalSize - 1);
48    const chunk = await downloadChunk(url, start, end);
49    const blob = await chunk.blob();
50    chunks.push(blob);
51  }
52  
53  return new Blob(chunks);
54}
Express.js: Support Range Requests
1// Server-side: Implement range request support
2const express = require('express');
3const fs = require('fs');
4const path = require('path');
5const app = express();
6
7// Helper to parse Range header
8function parseRange(rangeHeader, fileSize) {
9  if (!rangeHeader) return null;
10  
11  const match = rangeHeader.match(/bytes=(\d+)-(\d*)/);
12  if (!match) return null;
13  
14  const start = parseInt(match[1], 10);
15  const end = match[2] ? parseInt(match[2], 10) : fileSize - 1;
16  
17  if (start < 0 || end < start || start >= fileSize) {
18    return null; // Invalid range
19  }
20  
21  return { start, end };
22}
23
24// Serve file with range support
25app.get('/api/files/:filename', (req, res) => {
26  const filePath = path.join(__dirname, 'uploads', req.params.filename);
27  
28  if (!fs.existsSync(filePath)) {
29    return res.status(404).json({ error: 'File not found' });
30  }
31  
32  const stats = fs.statSync(filePath);
33  const fileSize = stats.size;
34  
35  // Set headers
36  res.set('Accept-Ranges', 'bytes');
37  res.set('Content-Length', fileSize);
38  
39  const range = parseRange(req.headers.range, fileSize);
40  
41  if (!range) {
42    // No range or invalid range - return 416 or full file
43    if (req.headers.range) {
44      return res.status(416)
45        .set('Content-Range', `bytes */${fileSize}`)
46        .json({ error: 'Range Not Satisfiable' });
47    }
48    // Return full file
49    return res.sendFile(filePath);
50  }
51  
52  // Valid range - return 206 Partial Content
53  const { start, end } = range;
54  const chunkSize = end - start + 1;
55  
56  res.status(206)
57    .set('Content-Range', `bytes ${start}-${end}/${fileSize}`)
58    .set('Content-Length', chunkSize);
59  
60  const stream = fs.createReadStream(filePath, { start, end });
61  stream.pipe(res);
62});
Nginx: Enable Range Request Support
1# Nginx: Configure range request support
2server {
3    listen 80;
4    server_name api.example.com;
5    root /var/www/files;
6    
7    location /api/files/ {
8        # Enable range requests
9        sendfile on;
10        tcp_nopush on;
11        
12        # Pass Range header to backend
13        proxy_set_header Range $http_range;
14        
15        # Backend should handle range requests
16        proxy_pass http://backend;
17        proxy_set_header Host $host;
18        proxy_set_header X-Real-IP $remote_addr;
19        
20        # Or serve files directly with Nginx range support
21        # try_files $uri =404;
22        # add_header Accept-Ranges bytes;
23    }
24    
25    # Direct file serving with range support (alternative)
26    location /files/ {
27        alias /var/www/files/;
28        sendfile on;
29        # Nginx automatically handles Range headers for static files
30        add_header Accept-Ranges bytes;
31    }
32}

Related Errors

Provider Information

This error code is specific to HTTP services. For more information, refer to the official HTTP documentation.

416 - Range Not Satisfiable | HTTP Error Reference | Error Code Reference