remotion-dev/remotion · error · Error

Range header (${requestedRange}) does not match content-rang

Error message

Range header (${requestedRange}) does not match content-range header (${parsedContentRange?.start})

What it means

validateContentRangeAndDetectIfSupported handles the numeric-range branch: when a number was requested, status is not 206, and parsedContentRange.start !== requestedRange, it throws unless requestedRange === 0 (which is treated as 'range not supported, serve everything'). The server's Content-Range start must match the byte offset the parser asked for.

Source

Thrown at packages/media-parser/src/readers/from-fetch.ts:67

	statusCode,
}: {
	requestedRange: number | [number, number];
	parsedContentRange: ParsedContentRange | null;
	statusCode: number;
}): {supportsContentRange: boolean} => {
	if (statusCode === 206) {
		return {supportsContentRange: true};
	}

	if (
		typeof requestedRange === 'number' &&
		parsedContentRange?.start !== requestedRange
	) {
		if (requestedRange === 0) {
			return {supportsContentRange: false};
		}

		throw new Error(
			`Range header (${requestedRange}) does not match content-range header (${parsedContentRange?.start})`,
		);
	}

	if (
		requestedRange !== null &&
		typeof requestedRange !== 'number' &&
		(parsedContentRange?.start !== requestedRange[0] ||
			parsedContentRange?.end !== requestedRange[1])
	) {
		throw new Error(
			`Range header (${requestedRange}) does not match content-range header (${parsedContentRange?.start})`,
		);
	}

	return {supportsContentRange: true};
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Ensure the server/CDN correctly implements Range: respond 206 with Content-Range: bytes N-M/T matching the requested start.
  2. Test with curl: `curl -v -r 1000-2000 <url>` and confirm Content-Range starts at 1000.
  3. Disable any transform/compression that breaks range fidelity for media MIME types.
  4. Move the asset to a Range-compliant host (S3, R2, static CDN) if the origin cannot be fixed.

Example fix

// before: origin ignores Range start
res.set('Content-Range', `bytes 0-${end}/${total}`); // always 0

// after: honor requested start
res.status(206)
  .set('Content-Range', `bytes ${start}-${end}/${total}`)
  .set('Content-Length', String(end - start + 1));
fs.createReadStream(file, {start, end}).pipe(res);
Defensive patterns

Strategy: validation

Validate before calling

// Verify Content-Range start matches the requested numeric offset
const r = await fetch(url, {headers: {Range: 'bytes=1000-'}});
const cr = r.headers.get('content-range'); // expect 'bytes 1000-.../...'
if (r.status !== 206 || !cr || !cr.startsWith('bytes 1000-')) {
  throw new Error('Server did not honor numeric Range start');
}

Try / catch

try {
  await parseMedia({src: url, fields: {durationInSeconds: true}});
} catch (e) {
  if (e instanceof Error && e.message.includes('does not match content-range')) {
    throw new Error('Origin Range compliance issue (numeric start mismatch)');
  }
  throw e;
}

Prevention

When it happens

Trigger: The parser requested `Range: bytes=N-` (N>0) and the server returned a Content-Range starting at a different offset (e.g. always 0, or a clamped/wrong start) with a 200-ish status. Indicates the server ignored or mis-answered the Range request.

Common situations: CDNs that clamp ranges, servers that always return the full file with a stale Content-Range header, load balancers rewriting ranges, or caches keyed incorrectly returning the wrong byte slice.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/86b2ce6f29999844. Report an issue: GitHub.