twentyhq/twenty · error · Error
download response is missing content-length
Error message
download response is missing content-length
What it means
The media-download flow requires a `Content-Length` header so it can pre-check the file size against `maxMediaFileSizeBytes` before streaming bytes. `parseContentLengthBytes` returns `undefined` when the header is missing or non-numeric; the code then cancels the response body and throws. Recall/media hosts that use chunked transfer encoding without a content-length therefore cannot be safely size-checked and are rejected.
Source
Thrown at packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts:217
if (!response.ok) {
await cancelMediaDownloadBody({
callRecordingId,
fileName,
body: response.body,
});
throw new Error(`download failed with status ${response.status}`);
}
if (isUndefined(contentLengthBytes)) {
await cancelMediaDownloadBody({
callRecordingId,
fileName,
body: response.body,
});
throw new Error('download response is missing content-length');
}
if (contentLengthBytes > maxMediaFileSizeBytes) {
await cancelMediaDownloadBody({
callRecordingId,
fileName,
body: response.body,
});
return { outcome: 'too-large', sizeBytes: contentLengthBytes };
}
if (isNull(response.body)) {
throw new Error('download returned no body');
}
return {
outcome: 'opened',View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Confirm with Recall.ai / the media host whether `Content-Length` is guaranteed; if they switched to chunked encoding, the downloader must be rewritten to size-check by streaming and accumulating byte counts up to the cap.
- Check for an intermediary (corporate proxy, egress gateway) stripping the header and bypass it for the Recall media host.
- If the artifact is still being transcoded, wait for Recall to report the recording fully ready before importing media.
- As a defensive change, fall back to streaming with a running byte counter and abort at `maxMediaFileSizeBytes` when content-length is absent.
Example fix
// before
if (isUndefined(contentLengthBytes)) {
await cancelMediaDownloadBody({ callRecordingId, fileName, body: response.body });
throw new Error('download response is missing content-length');
}
// after — when content-length is absent, stream with an enforced cap
if (isUndefined(contentLengthBytes)) {
if (isNull(response.body)) {
throw new Error('download returned no body and no content-length');
}
return {
outcome: 'opened',
body: wrapStreamWithByteCap(response.body, maxMediaFileSizeBytes, callRecordingId, fileName),
sizeBytes: 0,
};
} Defensive patterns
Strategy: validation
Validate before calling
const contentLengthBytes = parseContentLengthBytes(response.headers.get('content-length'));
if (isUndefined(contentLengthBytes)) {
// Option A: reject early with a clear message;
// Option B: stream with a running byte cap (see typeGuard/preventionTips).
await cancelMediaDownloadBody({ callRecordingId, fileName, body: response.body });
throw new Error(`download response for ${fileName} is missing content-length`);
} Type guard
const hasUsableContentLength = (res: Response): boolean => {
const v = res.headers.get('content-length');
const n = v == null ? NaN : Number(v.trim());
return Number.isFinite(n) && n >= 0;
}; Prevention
- Confirm with Recall/media host that Content-Length is guaranteed before relying on it for size gating.
- If the host may omit it, stream with a running byte counter that aborts at maxMediaFileSizeBytes instead of pre-checking.
- Log response headers on every download so a host/CDN change to chunked encoding is visible immediately.
- Bypass any proxy that strips Content-Length for the Recall media host.
When it happens
Trigger: The media host responds with `Transfer-Encoding: chunked` and no `Content-Length`, the header is empty/malformed, or an intermediary (CDN/proxy) strips it. Any of these makes `contentLengthBytes` undefined after parsing.
Common situations: Recall changes its media CDN to chunked encoding; a proxy in front of the runtime strips content-length; downloading an artifact still being finalized so the size is unknown.
Related errors
- download failed with status ${response.status}
- download returned no body
- failed to request artifact import for call recording ${callR
- RECALL_WEBHOOK_SECRET server variable is not set. A server a
- Raw request body was not forwarded by the server; cannot ver
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/ef205940f9a09c49.
Report an issue: GitHub.