remotion-dev/remotion · error · Error
No body
Error message
No body
What it means
getLengthAndReader throws 'No body' when, after ruling out the canLiveWithoutContentLength / requestedWithoutRange fast paths, res.body is null/undefined. The reader needs a ReadableStream body to pump bytes; without one it cannot deliver samples. This path is reached for ranged requests where Content-Length is present but the server returned an empty body.
Source
Thrown at packages/media-parser/src/readers/fetch/get-body-and-reader.ts:66
streamCancelled = true;
},
});
return {
contentLength: encoded.byteLength,
reader: {
reader: stream.getReader(),
abort: () => {
ownController.abort();
return Promise.resolve();
},
},
needsContentRange: false,
};
}
if (!res.body) {
throw new Error('No body');
}
const reader = res.body.getReader();
return {
reader: {
reader,
abort: () => {
ownController.abort();
return Promise.resolve();
},
},
contentLength,
needsContentRange: true,
};
};
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Ensure the server actually streams the media body for ranged GET requests (return a real ReadableStream / pipe the file).
- Verify the response status is 200 or 206 with a non-empty body using curl: `curl -v -r 0-100 <url>`.
- Check that no middleware (auth redirects, compression) is converting the response into a bodyless one.
- If you cannot fix the server, host the asset on a CDN/object store that serves bytes correctly.
Example fix
// before: serverless returns headers, no body
export default (req, res) => res.status(200).end();
// after: stream the actual bytes with Content-Length
import fs from 'node:fs';
export default (req, res) => {
const stat = fs.statSync(file);
res.set('Content-Length', String(stat.size)).set('Accept-Ranges','bytes');
fs.createReadStream(file).pipe(res);
}; Defensive patterns
Strategy: validation
Validate before calling
// Confirm ranged GET returns a body
const r = await fetch(url, {headers: {Range: 'bytes=0-99'}});
if (!r.body) throw new Error('Server returned no body for ranged GET'); Try / catch
try {
await parseMedia({src: url, fields: {durationInSeconds: true}});
} catch (e) {
if (e instanceof Error && e.message === 'No body') {
throw new Error('Media endpoint returned an empty body');
}
throw e;
} Prevention
- Ensure endpoints pipe real bytes for media GET requests.
- Test ranged responses with curl -v -r 0-100 <url>.
- Avoid serverless patterns that return headers without a body.
- Host media on a CDN/object store that streams bodies correctly.
When it happens
Trigger: A ranged fetch whose response has no body (res.body null) — e.g. a HEAD-like response, a server returning 200 with Content-Length but empty body, or an intermediary that swallowed the body. Reached only when not on the buffered/arrayBuffer path.
Common situations: Misconfigured serverless functions returning headers without a body, intermediaries that strip the body under certain conditions, 204/3xx mishandled as success, or a server that closed the stream immediately.
Related errors
- HTTP error, status = ${res.status}
- HTTP response of ${srcWithoutHash} has no body
- Server returned status ${res.status} while fetching ${actual
- Cannot read media ${src} without a content length. This is c
- Cannot read media without it supporting the "Content-Range"
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/cd8db062dd16c056.
Report an issue: GitHub.