{"record":{"id":"2691067d1a07d636","repo":"gitroomhq/postiz-app","slug":"failed-to-upload-the-media-file-269106","errorCode":null,"errorMessage":"Failed to upload the media file","messagePattern":"Failed to upload the media file","errorType":"exception","errorClass":"BadBody","httpStatus":null,"severity":"error","filePath":"libraries/nestjs-libraries/src/integrations/social/whop.provider.ts","lineNumber":296,"sourceCode":"        });\n        if (!fileResponse.ok || !fileResponse.body) {\n          throw new Error(`Failed to fetch media: ${fileResponse.statusText}`);\n        }\n        const uploadResponse = await fetch(createFileResponse.upload_url, {\n          method: 'PUT',\n          headers: {\n            // Whop's own upload_headers win if they ever include a length.\n            'Content-Length': String(contentLength),\n            ...(createFileResponse.upload_headers || {}),\n          },\n          body: fileResponse.body,\n          // Required by undici when streaming a request body.\n          duplex: 'half',\n        } as any);\n        // A rejected PUT leaves the file pending forever - fail fast instead\n        // of burning the ~9 minute status poll below.\n        if (!uploadResponse.ok) {\n          throw new BadBody(\n            this.identifier,\n            await uploadResponse.text().catch(() => '{}'),\n            '{}',\n            'Failed to upload the media file'\n          );\n        }\n\n        let uploadStatus = 'pending';\n        let attempts = 0;\n        const maxAttempts = 108; // ~9 minutes at 5s interval\n        while (uploadStatus !== 'ready') {\n          if (attempts++ >= maxAttempts) {\n            throw new Error('File upload timed out');\n          }\n\n          const fileStatus = await (\n            await this.fetch(\n              `https://api.whop.com/api/v1/files/${createFileResponse.id}`,","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/integrations/social/whop.provider.ts#L278-L314","documentation":"The PUT of media bytes to Whop's upload_url returned a non-ok status. Because a rejected PUT leaves the file 'pending' forever, it fails fast with BadBody instead of burning the ~9-minute status poll.","triggerScenarios":"Whop's file upload endpoint rejects the PUT: expired upload_url, wrong Content-Length header (does not match actual streamed bytes), content-type mismatch, or size exceeding Whop's limit.","commonSituations":"Media file changed size between HEAD and PUT; Whop upload headers requirements changed; slow networks letting the signed upload_url expire before the PUT starts.","solutions":["Read the response text attached to the BadBody for Whop's rejection reason","Ensure the Content-Length matches the actual byte stream being PUT (don't transcode/resize mid-flight)","Retry the post to get a fresh upload_url","Verify the file is within Whop's size/type limits"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if (contentLength !== actualBytes.length) { /* abort before PUT; sizes must match */ }","typeGuard":null,"tryCatchPattern":"catch (e) { if (e instanceof BadBody && e.message.includes('upload the media file')) { /* retry post for a fresh upload_url; inspect attached response text */ } throw e; }","preventionTips":["Stream exactly Content-Length bytes on the PUT","Start the PUT promptly after obtaining upload_url","Validate file type/size against Whop's limits before uploading"],"tags":["whop","file-upload","put-rejected"],"backgroundTag":"social-media-upload-rejected","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}