{"record":{"id":"e5163201e9abed60","repo":"linshenkx/prompt-optimizer","slug":"s3-download-returned-an-unsupported-response-body","errorCode":null,"errorMessage":"S3 download returned an unsupported response body","messagePattern":"S3 download returned an unsupported response body","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utils/remote-backup.ts","lineNumber":701,"sourceCode":"    const chunks: Uint8Array[] = []\n    let total = 0\n    for (;;) {\n      const { done, value } = await reader.read()\n      if (done) break\n      if (!value) continue\n      chunks.push(value)\n      total += value.byteLength\n    }\n    const bytes = new Uint8Array(total)\n    let offset = 0\n    for (const chunk of chunks) {\n      bytes.set(chunk, offset)\n      offset += chunk.byteLength\n    }\n    return bytes.buffer\n  }\n\n  throw new Error('S3 download returned an unsupported response body')\n}\n\nconst isS3NotFoundError = (error: unknown): boolean => {\n  const value = error as {\n    name?: string\n    Code?: string\n    code?: string\n    $metadata?: { httpStatusCode?: number }\n  }\n  return value?.$metadata?.httpStatusCode === 404 ||\n    value?.name === 'NotFound' ||\n    value?.name === 'NoSuchKey' ||\n    value?.Code === 'NoSuchKey' ||\n    value?.code === 'NoSuchKey'\n}\n\nconst s3ErrorMessage = (error: unknown): string =>\n  (error as Error)?.message || String(error)","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/utils/remote-backup.ts#L683-L719","documentation":"Thrown by s3BodyToArrayBuffer when the S3 (or S3-compatible) response body cannot be coerced to bytes: it handles empty bodies, ArrayBuffer, Uint8Array, and streaming chunked bodies, and throws this error for anything else (e.g. a Blob or string body).","triggerScenarios":"S3 client (or custom endpoint/proxy like MinIO, R2, or an API gateway) returning the object body as a Blob, ReadableStream of non-Uint8Array chunks, string, or an SDK version whose body type is not handled; head requests or pre-signed URL fetches returning unexpected representations.","commonSituations":"Switching S3 SDK versions where getObject().Body changed shape (v2 stream vs v3 sdkStreamMixin); browser fetch returning a Blob because response.blob() was called instead of arrayBuffer(); S3-compatible backends (MinIO/Ceph) with differing response encodings; middleware converting streams.","solutions":["Inspect the actual body type at runtime (body?.constructor?.name) to identify the unexpected shape","Convert before calling: use response.arrayBuffer() for fetch responses, orSdkStreamMixin/transform in AWS SDK v3 to normalize Body","Pin or upgrade the S3 SDK to a version whose body shape the helper supports","If using an S3-compatible gateway, ensure it returns standard binary octet-stream responses"],"exampleFix":"// before\nconst body = await s3.send(new GetObjectCommand({ Key })).Body // unknown shape\n// after - normalize fetch-style responses first\nconst resp = await fetch(signedUrl)\nconst body = await resp.arrayBuffer() // ArrayBuffer is always accepted\nconst buf = await s3BodyToArrayBuffer(body)","handlingStrategy":"type-guard","validationCode":"const normalizeS3Body = async (body: unknown): Promise<ArrayBuffer | Uint8Array | null> => {\n  if (!body) return null\n  if (body instanceof Blob) return await body.arrayBuffer()\n  if (typeof body === 'string') return new TextEncoder().encode(body)\n  return (body as ArrayBuffer | Uint8Array) ?? null\n}","typeGuard":"const isSupportedS3Body = (\n  body: unknown,\n): body is ArrayBuffer | Uint8Array =>\n  body instanceof ArrayBuffer || body instanceof Uint8Array","tryCatchPattern":"try {\n  const buf = await s3BodyToArrayBuffer(body)\n} catch (error) {\n  if ((error as Error).message.includes('unsupported response body')) {\n    const resp = (body as unknown as { transformToByteArray?: () => Promise<Uint8Array> })\n    if (typeof resp.transformToByteArray === 'function') {\n      return await s3BodyToArrayBuffer(await resp.transformToByteArray())\n    }\n  }\n  throw error\n}","preventionTips":["Normalize SDK v3 streams with transformToByteArray before passing bodies","Pin the AWS SDK version in package.json to avoid body-shape drift","Use response.arrayBuffer() for fetch-based pre-signed URL downloads"],"tags":["s3","binary-data","response-body","aws-sdk"],"backgroundTag":"unsupported-response-body-type","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}