twentyhq/twenty · error · Error

download returned no body

Error message

download returned no body

What it means

After the content-length checks pass, the downloader asserts `response.body` is a non-null `ReadableStream`. A null body means the fetch runtime did not provide a stream to read from, so there is nothing to upload; the code throws rather than proceed. This is distinct from a missing content-length (26) or a non-ok status (25).

Source

Thrown at packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts:231

      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',
    body: response.body,
    sizeBytes: contentLengthBytes,
  };
};

const uploadMediaStreamToStorage = async ({
  callRecordingId,
  metadataClient,
  fileName,
  fieldMetadataUniversalIdentifier,
  body,
  sizeBytes,
}: {
  callRecordingId: string;

View on GitHub (pinned to 1f5dd2bbd2)

Solutions

  1. Confirm the runtime/polyfill providing `fetch` supports `ReadableStream` bodies (Node 18+ undici does; older polyfills may not).
  2. Ensure nothing consumes `response.body` (e.g. a logging hook calling `.json()`/`.text()`) before this point.
  3. If the host genuinely returns empty bodies for some artifacts, guard earlier and mark that artifact as unavailable instead of throwing.
  4. Log `response.headers` and status alongside the null-body check to distinguish a host issue from a runtime issue.

Example fix

// before
if (isNull(response.body)) {
  throw new Error('download returned no body');
}

// after — distinguish runtime-missing-stream from host-empty-body
if (isNull(response.body)) {
  throw new Error(
    `download returned no body for ${fileName} (status=${response.status}, contentLength=${contentLengthBytes}); fetch runtime may not expose ReadableStream bodies`,
  );
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Confirm the runtime exposes a streaming fetch body before importing media.
if (typeof Response === 'undefined' || typeof ReadableStream === 'undefined') {
  throw new Error('Runtime does not support streaming response bodies; cannot import media');
}

Type guard

const hasStreamingBody = (res: Response): res is Response & { body: ReadableStream<Uint8Array> } =>
  !isNull(res.body) && typeof (res.body as ReadableStream<Uint8Array>).getReader === 'function';

Prevention

When it happens

Trigger: The fetch implementation in use does not expose streaming bodies (some runtimes/polyfills return `body: null`), the response was already consumed/cancelled upstream, or the media host returned a 2xx with an empty body that the runtime represents as null.

Common situations: Running the logic function in a runtime whose `fetch` does not implement streaming bodies; a polyfill mismatch; or a logic-function platform update that changed how response bodies are exposed.

Related errors


AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12). Data as JSON: /api/errors/4d140c7911fe0311. Report an issue: GitHub.