remotion-dev/remotion · warning · Error
Unexpected error: content-length is null
Error message
Unexpected error: content-length is null
What it means
After a successful HEAD request (status 200), `getAssetMetadata()` reads the `content-length` header to determine asset size (packages/studio/src/helpers/get-asset-metadata.ts:80). If the header is absent or empty, it throws this error (caught and shown as `metadata-error`). It means the server answered 200 but did not declare a body length, which happens with chunked or compressed responses and proxies that strip the header.
Source
Thrown at packages/studio/src/helpers/get-asset-metadata.ts:141
if (size === null) {
const file = await fetch(src, {
method: 'HEAD',
});
if (file.status === 404) {
return {type: 'not-found'};
}
if (file.status !== 200) {
throw new Error(
`Expected status code 200 or 404 for file, got ${file.status}`,
);
}
const contentLength = file.headers.get('content-length');
if (!contentLength) {
throw new Error('Unexpected error: content-length is null');
}
size = Number(contentLength);
}
const fetchedAt = Date.now();
const srcWithTime = addTime ? addAssetCacheBust({fetchedAt, src}) : src;
const fileType = getPreviewFileType(
canvasContent.type === 'asset' ? canvasContent.asset : src,
);
if (fileType === 'video' || fileType === 'audio') {
const mediaMetadata = await getMediaMetadata(srcWithTime);
if (mediaMetadata === null) {
throw new Error(`Could not read media metadata for ${src}`);
}
View on GitHub (pinned to b2f4e34732)
Solutions
- Configure the server to include `Content-Length` on HEAD responses for assets — typically by disabling compression/chunking for that route or using static file serving that sets the header.
- Serve the file statically from the project `public/` folder instead of a dynamic route, so Studio reads the size from the static-file listing and never performs the HEAD request.
- Bypass intermediaries that strip the header (check with `curl -I` through the same path Studio uses) or reconfigure the proxy to forward content-length.
Example fix
// before: dynamic/compressed route answers HEAD 200 without a length
app.use(compression());
app.get('/assets/:name', (req, res) => res.sendFile(dynamicPath));
// after: uncompressed static serving sends Content-Length
app.use('/assets', express.static(assetsDir)); // HEAD now includes content-length Defensive patterns
Strategy: validation
Validate before calling
const headHasLength = async (src: string): Promise<boolean> => {
const res = await fetch(src, {method: 'HEAD'});
if (res.status !== 200) return false;
const len = res.headers.get('content-length');
return len != null && len !== '';
};
if (!(await headHasLength(src))) {
// reconfigure the asset host to send Content-Length before relying on Studio metadata
} Prevention
- Serve assets from static file handlers that set `Content-Length`; disable compression/chunked encoding on asset routes.
- Keep timeline assets out of dynamic/serverless routes that stream responses without a length.
- Verify hosts with `curl -I` through the exact URL/proxy chain Studio uses.
- Place files in the Studio project's `public/` folder when possible — the static-file listing carries the size and skips the HEAD path entirely.
When it happens
Trigger: A timeline asset/output URL whose HEAD response omits `Content-Length`: dynamically generated responses (chunked transfer-encoding), compression middleware that drops the length on HEAD, or intermediary proxies/HTTP2 servers that omit it. The 200 check at line 74 passes, then line 82 fires on the null header.
Common situations: Dev servers with compression enabled (Vite/Express `compression`) answering HEAD chunked; assets served from dynamic routes or serverless functions without an explicit length; reverse proxies (nginx defaults, some corporate proxies) removing content-length; assets served cross-origin through CDNs that stream responses.
Related errors
- Expected status code 200 or 404 for file, got ${file.status}
- Studio server port should be a number. Got ${typeof port} ($
- Studio server port should be a number between 1 and 65535. G
- Job is not running
- Invalid render type, must be either "media" or "still"
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-08-22).
Data as JSON: /api/errors/6fce86fe0b6068d8.
Report an issue: GitHub.