{"record":{"id":"ef205940f9a09c49","repo":"twentyhq/twenty","slug":"download-response-is-missing-content-length","errorCode":null,"errorMessage":"download response is missing content-length","messagePattern":"download response is missing content-length","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts","lineNumber":217,"sourceCode":"\n  if (!response.ok) {\n    await cancelMediaDownloadBody({\n      callRecordingId,\n      fileName,\n      body: response.body,\n    });\n\n    throw new Error(`download failed with status ${response.status}`);\n  }\n\n  if (isUndefined(contentLengthBytes)) {\n    await cancelMediaDownloadBody({\n      callRecordingId,\n      fileName,\n      body: response.body,\n    });\n\n    throw new Error('download response is missing content-length');\n  }\n\n  if (contentLengthBytes > maxMediaFileSizeBytes) {\n    await cancelMediaDownloadBody({\n      callRecordingId,\n      fileName,\n      body: response.body,\n    });\n\n    return { outcome: 'too-large', sizeBytes: contentLengthBytes };\n  }\n\n  if (isNull(response.body)) {\n    throw new Error('download returned no body');\n  }\n\n  return {\n    outcome: 'opened',","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts#L199-L235","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif (isUndefined(contentLengthBytes)) {\n  await cancelMediaDownloadBody({ callRecordingId, fileName, body: response.body });\n  throw new Error('download response is missing content-length');\n}\n\n// after — when content-length is absent, stream with an enforced cap\nif (isUndefined(contentLengthBytes)) {\n  if (isNull(response.body)) {\n    throw new Error('download returned no body and no content-length');\n  }\n  return {\n    outcome: 'opened',\n    body: wrapStreamWithByteCap(response.body, maxMediaFileSizeBytes, callRecordingId, fileName),\n    sizeBytes: 0,\n  };\n}","handlingStrategy":"validation","validationCode":"const contentLengthBytes = parseContentLengthBytes(response.headers.get('content-length'));\nif (isUndefined(contentLengthBytes)) {\n  // Option A: reject early with a clear message;\n  // Option B: stream with a running byte cap (see typeGuard/preventionTips).\n  await cancelMediaDownloadBody({ callRecordingId, fileName, body: response.body });\n  throw new Error(`download response for ${fileName} is missing content-length`);\n}","typeGuard":"const hasUsableContentLength = (res: Response): boolean => {\n  const v = res.headers.get('content-length');\n  const n = v == null ? NaN : Number(v.trim());\n  return Number.isFinite(n) && n >= 0;\n};","tryCatchPattern":null,"preventionTips":["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."],"tags":["network","recall","call-recorder","media-download","http-headers"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}