gitroomhq/postiz-app · error · BadBody

Could not determine the media size for upload

Error message

Could not determine the media size for upload

What it means

uploadMediaToWhop does a HEAD request to determine the media's content-length; if the HEAD fails or returns no content-length it throws BadBody 'Could not determine the media size for upload' as a permanent (non-retryable) condition.

Source

Thrown at libraries/nestjs-libraries/src/integrations/social/whop.provider.ts:247

    const attachments: { id: string }[] = [];

    for (const item of media) {
      // The size comes from a HEAD request; the PUT below streams the bytes
      // so the file is never buffered in memory (it used to stay resident
      // through the whole ~9 minute status poll).
      const headResponse = await fetch(item.path, {
        method: 'HEAD',
        // identity encoding so content-length matches the bytes the GET streams
        headers: { 'accept-encoding': 'identity' },
        // @ts-ignore - undici-only option; blocks SSRF to internal IPs
        dispatcher: getSsrfSafeDispatcher(),
      });
      const contentLength = Number(
        headResponse.headers.get('content-length') || 0
      );
      if (!headResponse.ok || !contentLength) {
        // A permanent condition - fail fast instead of letting Temporal retry
        throw new BadBody(
          this.identifier,
          '{}',
          '{}',
          'Could not determine the media size for upload'
        );
      }
      const fileName = item.path.split('/').pop() || 'file';

      const createFileResponse = await (
        await this.fetch(
          'https://api.whop.com/api/v1/files',
          {
            method: 'POST',
            headers: {
              Authorization: `Bearer ${accessToken}`,
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({

View on GitHub (pinned to 0f1647f749)

Solutions

  1. curl -I the media URL and confirm a 200 with a Content-Length header
  2. Re-upload the media to get a fresh URL, then retry the post
  3. If your storage doesn't support HEAD, serve media from one that does (S3/compatible)
  4. Ensure nothing strips Content-Length (e.g. on-the-fly gzip) for HEAD requests
Defensive patterns

Strategy: validation

Validate before calling

const head = await fetch(mediaUrl, { method: 'HEAD' });
if (!head.ok || !Number(head.headers.get('content-length'))) { /* re-upload media or block the post before calling uploadMediaToWhop */ }

Type guard

const hasKnownSize = (h: Headers) => h.get('content-length') !== null && Number(h.headers?.['content-length']) > 0;

Try / catch

catch (e) { if (e instanceof BadBody && e.message.includes('media size')) { /* permanent: re-add media, do not retry */ } throw e; }

Prevention

When it happens

Trigger: HEAD on the media URL returns non-2xx (expired presigned URL, 403, 404) or lacks a Content-Length header (chunked/compressed encoding, or storage that refuses HEAD).

Common situations: Media stored behind services that don't answer HEAD (some CDns/serverless stores); presigned URL expired before the upload ran; media deleted from the library while the post was pending.

Related errors


AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27). Data as JSON: /api/errors/bac3d36b07ffc6f0. Report an issue: GitHub.