gitroomhq/postiz-app · error · BadBody

Could not determine the video size for the YouTube upload

Error message

Could not determine the video size for the YouTube upload

What it means

During a resumable YouTube upload, the provider issues an HTTP HEAD request against the stored media URL and expects a content-length header so it can compute the video size. If the storage endpoint responds without content-length (or the header is empty), a BadBody error is thrown because the upload byte range cannot be calculated.

Source

Thrown at libraries/nestjs-libraries/src/integrations/social/youtube.provider.ts:445

  private static readonly YOUTUBE_UPLOAD_BATCH_MS = 4 * 60 * 1000;

  // Resolves the total byte size of the media without loading it into memory:
  // a HEAD request for remote URLs, statSync for local files.
  private async youtubeMediaSize(path: string): Promise<number> {
    if (path.indexOf('http') === 0) {
      // the media path is user-influenced, keep the SSRF-safe dispatcher that
      // this.fetch applies to every other outbound request. identity encoding
      // so content-length matches the bytes a later GET actually streams
      // (fetch transparently decompresses encoded bodies).
      setHeartbeatDetails(`youtube: media size ${stripQuery(path)}`);
      const head = await fetch(path, {
        method: 'HEAD',
        headers: { 'accept-encoding': 'identity' },
        dispatcher: getSsrfSafeDispatcher(),
      } as any);
      const length = head.headers.get('content-length');
      if (!length) {
        throw new BadBody(
          this.identifier,
          '{}',
          '{}',
          'Could not determine the video size for the YouTube upload'
        );
      }
      return Number(length);
    }

    return statSync(path).size;
  }

  // Returns a streaming body for the [start, end] byte range of the media so we
  // never hold the whole file in memory: a ranged GET for remote URLs, a ranged
  // read stream for local files.
  private async youtubeChunkStream(path: string, start: number, end: number) {
    if (path.indexOf('http') === 0) {
      // identity encoding so the store keeps content-length and can answer

View on GitHub (pinned to 0f1647f749)

Solutions

  1. Verify the media URL returns content-length: curl -I on the stored asset URL
  2. If using a proxy/CDN, configure it to pass through content-length on HEAD requests
  3. Ensure uploads store the file size so the origin can serve accurate HEAD metadata
  4. Retry the post after fixing storage so a fresh media URL is generated

Example fix

// before
const length = head.headers.get('content-length');
if (!length) { throw new BadBody(...); }

// after (fallback: fail fast at upload time by validating the media record)
const length = head.headers.get('content-length');
if (!length) {
  throw new BadBody(
    this.identifier, '{}', '{}',
    'Could not determine the video size for the YouTube upload'
  );
}
// caller-side: assert media.size is present before scheduling the video post
Defensive patterns

Strategy: validation

Validate before calling

const head = await fetch(mediaUrl, { method: 'HEAD', headers: { 'accept-encoding': 'identity' } });
if (!head.headers.get('content-length')) {
  throw new Error('Media URL has no content-length; fix storage before posting');
}

Type guard

const hasContentLength = (h: Headers): boolean => Boolean(h.get('content-length'));

Try / catch

catch (e) { if (/Could not determine the video size/.test(e.message)) { fixStorageHeaders(); } throw e; }

Prevention

When it happens

Trigger: Calling the YouTube provider's upload flow (postPending/post of a video post) where the media URL is served by a storage layer that omits content-length on HEAD requests (e.g. chunked/streaming responses, signed URLs stripped of the header, or a redirect to a server that doesn't return it).

Common situations: Self-hosted S3-compatible storage (MinIO) or CDNs/proxies that drop content-length; media served with content-encoding/compression making length unknown; expired or misconfigured signed URLs returning an error page without the header.

Related errors


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