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 answerView on GitHub (pinned to 0f1647f749)
Solutions
- Verify the media URL returns content-length: curl -I on the stored asset URL
- If using a proxy/CDN, configure it to pass through content-length on HEAD requests
- Ensure uploads store the file size so the origin can serve accurate HEAD metadata
- 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
- Verify storage returns content-length on HEAD before scheduling video posts
- Store the media size at upload time and validate it exists
- Avoid proxies that strip content-length
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
- 'Could not determine the media size for upload'
- The media storage did not return the requested byte range, p
- Failed to fetch URL
- File is too large.
- Unsupported file type.
AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27).
Data as JSON: /api/errors/7f92f12d97f9304b.
Report an issue: GitHub.