{"record":{"id":"a2dbd5699f29c6fa","repo":"gitroomhq/postiz-app","slug":"the-media-storage-did-not-return-the-requested-byt","errorCode":null,"errorMessage":"The media storage did not return the requested byte range, please try again","messagePattern":"The media storage did not return the requested byte range, please try again","errorType":"exception","errorClass":"BadBody","httpStatus":null,"severity":"error","filePath":"libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts","lineNumber":709,"sourceCode":"  // Returns a streaming body for the [start, end] byte range of the media so we\n  // never hold the whole file in memory: a ranged GET for remote URLs, a ranged\n  // read stream for local files.\n  private async tiktokChunkStream(path: string, start: number, end: number) {\n    if (path.indexOf('http') === 0) {\n      // identity encoding so the store keeps content-length and can answer\n      // with the requested range, matching every other media read\n      const response = await fetch(path, {\n        headers: {\n          Range: `bytes=${start}-${end}`,\n          'accept-encoding': 'identity',\n        },\n        dispatcher: getSsrfSafeDispatcher(),\n      } as any);\n\n      // A store that ignores Range (200 with the full file) or answers with an\n      // error page would corrupt the upload at this offset.\n      if (response.status !== 206) {\n        throw new BadBody(\n          'tiktok-error-upload',\n          '{}',\n          '{}',\n          'The media storage did not return the requested byte range, please try again'\n        );\n      }\n\n      return response.body;\n    }\n\n    return createReadStream(path, { start, end });\n  }\n\n  // Streams the video bytes to the upload_url returned by the init call.\n  // We use the global fetch (not this.fetch) because chunked uploads answer\n  // with 206 (Partial Content), which this.fetch would treat as an error.\n  private async uploadTikTokVideoBytes(\n    uploadUrl: string,","sourceCodeStart":691,"sourceCodeEnd":727,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts#L691-L727","documentation":"tiktokChunkStream expected a 206 Partial Content response when requesting a byte range from media storage, but got another status (typically 200 or an error page). This guards the chunked upload against stores that ignore the Range header, which would corrupt the video data written at that offset.","triggerScenarios":"A GET with a Range header against the media URL returns 200 (full file), 4xx/5xx, or a proxy/WAF HTML page instead of 206. Happens with media-storage presigned URLs that don't support ranges, expired signed URLs redirecting to a login page, or CDNs stripping the Range header.","commonSituations":"Self-hosted or S3-compatible storage misconfigured for range requests; expired presigned media URLs; a reverse proxy in front of storage that drops Range headers; uploading large TikTok videos >~64MB which force chunked mode.","solutions":["Verify the media URL returns 206 with curl: curl -H 'Range: bytes=0-1023' -I <media-url>","If storage ignores Range, fix its configuration (enable range support / use a store that supports it) so chunked upload is possible","Regenerate/re-upload the media so the presigned URL is fresh, then retry the post","If the media is small enough, let TikTok use non-chunked upload instead of tiktokChunkStream"],"exampleFix":"// before\nconst response = await fetch(url, { headers: { Range: `bytes=${start}-${end}` } });\nconst chunk = await response.arrayBuffer(); // corrupt if status is 200\n\n// after\nconst response = await fetch(url, { headers: { Range: `bytes=${start}-${end}` } });\nif (response.status !== 206) {\n  throw new BadBody('tiktok-error-upload', '{}', '{}',\n    'The media storage did not return the requested byte range, please try again');\n}","handlingStrategy":"validation","validationCode":"const resp = await fetch(mediaUrl, { method: 'HEAD' });\nconst acceptRanges = resp.headers.get('accept-ranges');\nif (!acceptRanges?.includes('bytes')) {\n  // avoid chunked upload path or copy media to range-capable storage first\n}","typeGuard":"const isRangeResponse = (r: Response): boolean => r.status === 206 && r.headers.has('content-range');","tryCatchPattern":"catch (e) { if (e instanceof BadBody && e.message.includes('byte range')) { /* refetch media URL / re-upload media, then retry once */ } throw e; }","preventionTips":["Use media storage that honors Range requests (S3/R2/compatible)","Keep presigned media URLs fresh; re-upload media if a post stays pending long","Health-check media URLs with a HEAD + Range probe before starting chunked uploads"],"tags":["tiktok","video-upload","http-range","media-storage","chunked-upload"],"backgroundTag":"http-range-not-honored","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}