remotion-dev/remotion · error · Error
Cannot read media without it supporting the "Content-Range"
Error message
Cannot read media without it supporting the "Content-Range" header. This is currently not supported. Ensure the media supports the "Content-Range" HTTP header.
What it means
After the first read, internalParseMedia rejects when supportsContentRange is false yet needsContentRange is true. needsContentRange becomes true when the reader had to stream a partial body without a buffered arrayBuffer (the generic path in getLengthAndReader). supportsContentRange is derived from the server honoring Range / returning 206. Without range support the parser cannot seek, so it aborts early.
Source
Thrown at packages/media-parser/src/internal-parse-media.ts:87
contentType,
supportsContentRange,
needsContentRange,
} = await readerInterface.read({
src,
range: null,
controller,
logLevel,
prefetchCache,
});
if (contentLength === null) {
throw new Error(
`Cannot read media ${src} without a content length. This is currently not supported. Ensure the media has a "Content-Length" HTTP header.`,
);
}
if (!supportsContentRange && needsContentRange) {
throw new Error(
'Cannot read media without it supporting the "Content-Range" header. This is currently not supported. Ensure the media supports the "Content-Range" HTTP header.',
);
}
const hasAudioTrackHandlers = Boolean(onAudioTrack);
const hasVideoTrackHandlers = Boolean(onVideoTrack);
const state = makeParserState({
hasAudioTrackHandlers,
hasVideoTrackHandlers,
controller,
onAudioTrack: onAudioTrack ?? null,
onVideoTrack: onVideoTrack ?? null,
contentLength,
logLevel,
mode,
readerInterface,
src,View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Enable HTTP Range support on the server (static file servers do this automatically; Express: use `express.static` or `serve-static`).
- Remove middleware (compression, brotli) that transforms the body and breaks Range for media MIME types.
- Host media on a CDN/object store that supports Range (S3, Cloudflare R2, Vercel static).
- For local files in Node, pass `reader: nodeReader` to bypass HTTP range entirely.
Example fix
// before
app.get('/v', (req,res) => fs.createReadStream(file).pipe(res));
// after: honor Range
const stat = fs.statSync(file);
const range = req.range(stat.size);
if (range && range.type === 'bytes' && range.length) {
const {start, end} = range[0];
res.status(206)
.set('Content-Range', `bytes ${start}-${end}/${stat.size}`)
.set('Content-Length', String(end - start + 1))
.set('Accept-Ranges', 'bytes');
fs.createReadStream(file, {start, end}).pipe(res);
} else {
res.set('Accept-Ranges', 'bytes').set('Content-Length', String(stat.size));
fs.createReadStream(file).pipe(res);
} Defensive patterns
Strategy: validation
Validate before calling
// Confirm the server honors Range (returns 206)
const r = await fetch(url, {method: 'GET', headers: {Range: 'bytes=0-1'}});
if (r.status !== 206 || !r.headers.get('content-range')) {
throw new Error('Server does not support HTTP Range; parser cannot seek');
} Try / catch
try {
await parseMedia({src: url, fields: {durationInSeconds: true}});
} catch (e) {
if (e instanceof Error && e.message.includes('Content-Range')) {
throw new Error('Media host must support Range requests');
}
throw e;
} Prevention
- Host media on Range-compliant storage (S3, R2, static CDN, express.static).
- Remove body-transforming middleware for media MIME types.
- Test Range support with curl -r 0-100 before integrating.
- For local files, use nodeReader to avoid HTTP range entirely.
When it happens
Trigger: A server that serves the full body with a 200 (ignoring the Range header) and does not return Content-Length in a way that lets the reader buffer fully — combined with a media format that requires seeking (most non-.m3u8/.ts ISO-BMFF or Matroska files).
Common situations: Static hosts that don't implement Range (some serverless functions, Express routes that always pipe the whole file), intermediaries that merge range requests, or compression middleware that breaks range requests. Contrast with 1504 which fires when total length is unknown; this fires when length is known but seeking is impossible.
Related errors
- Range header (${requestedRange}) does not match content-rang
- Cannot read media ${src} without a content length. This is c
- Server returned status code ${res.status} for ${resolvedUrl}
- Expected stco box in trak box
- No sample found
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/0ec45e0f608f2e41.
Report an issue: GitHub.