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

  1. Ensure the server actually streams the media body for ranged GET requests (return a real ReadableStream / pipe the file).
  2. Verify the response status is 200 or 206 with a non-empty body using curl: `curl -v -r 0-100 <url>`.
  3. Check that no middleware (auth redirects, compression) is converting the response into a bodyless one.
  4. 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

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


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