gitroomhq/postiz-app · error · Error
Failed to fetch media: ${fileResponse.statusText}
Error message
Failed to fetch media: ${fileResponse.statusText} What it means
While uploading media to Whop, the GET of the media file failed (non-ok status or empty body) and it throws with the fetch statusText. Fetch uses an SSRF-safe dispatcher, so internal/unreachable hosts also fail here.
Source
Thrown at libraries/nestjs-libraries/src/integrations/social/whop.provider.ts:280
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
filename: fileName,
}),
},
'create file record'
)
).json();
if (createFileResponse.upload_url) {
const fileResponse = await fetch(item.path, {
headers: { 'accept-encoding': 'identity' },
// @ts-ignore - undici-only option; blocks SSRF to internal IPs
dispatcher: getSsrfSafeDispatcher(),
});
if (!fileResponse.ok || !fileResponse.body) {
throw new Error(`Failed to fetch media: ${fileResponse.statusText}`);
}
const uploadResponse = await fetch(createFileResponse.upload_url, {
method: 'PUT',
headers: {
// Whop's own upload_headers win if they ever include a length.
'Content-Length': String(contentLength),
...(createFileResponse.upload_headers || {}),
},
body: fileResponse.body,
// Required by undici when streaming a request body.
duplex: 'half',
} as any);
// A rejected PUT leaves the file pending forever - fail fast instead
// of burning the ~9 minute status poll below.
if (!uploadResponse.ok) {
throw new BadBody(
this.identifier,
await uploadResponse.text().catch(() => '{}'),View on GitHub (pinned to 0f1647f749)
Solutions
- curl the media URL from the worker machine to confirm reachability and a 200
- Re-add the media to the post so a fresh URL is generated
- If self-hosting, ensure the storage host is publicly resolvable/reachable from the orchestrator workers
- Check statusText/body in logs for the exact HTTP failure and fix that (403 vs 404 vs DNS)
Defensive patterns
Strategy: retry
Validate before calling
const testFetch = await fetch(mediaUrl, { method: 'HEAD', dispatcher: getSsrfSafeDispatcher() } as any);
if (!testFetch.ok) { /* refresh media URL or fail before upload */ } Try / catch
catch (e) { if (e instanceof Error && e.message.startsWith('Failed to fetch media')) { /* transient network: retry with backoff; permanent if 403/404 */ } throw e; } Prevention
- Keep media hosts publicly reachable from workers (SSRF-safe dispatcher blocks internal IPs)
- Probe media URLs before scheduling-dependent uploads
- Re-upload media when presigned URLs are near expiry
When it happens
Trigger: GET on item.path returns 403/404 (expired presigned URL), DNS/network failure, or the URL points at a private IP which the SSRF-safe dispatcher blocks.
Common situations: Expired media URLs in pending posts; media host temporarily down; self-hosted storage on an internal hostname unreachable from the worker; presigned URL signed for a different request (e.g. GET disallowed).
Related errors
- Failed to fetch URL
- Failed to fetch media: ${fileResponse.statusText}
- Could not determine the media size for upload
- Could not determine the media size for upload
- Failed to upload the media file
AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27).
Data as JSON: /api/errors/a805abecde42a362.
Report an issue: GitHub.