payload icon indicating copy to clipboard operation
payload copied to clipboard

storage-vercel-blob: Upload fails sometimes when using `clientUpload: true`

Open FlavioReinhard opened this issue 1 month ago • 3 comments

Describe the Bug

Edit: Previously, I was able to reproduce it around 30% of the time. Classical: Now it seems to happen less often. Hard to say what has changed, and I am using the same files.

When using @payloadcms/storage-vercel-blob with clientUpload: true, image uploads fail sometimes with the reproduction repo (blank payload project + vercel blob storage plugin).

The network tab shows that

  • vercel-blob-client-upload-route correctly creates a token
  • the upload of the file to vercel is also successful
  • but the following POST call to /api/media?depth=0&fallback-locale=null fails with 400.

The logs indicate an issue with getImageSize in generateFileData:

[23:45:22] ERROR: unsupported file type: undefined
    err: {
      "type": "TypeError",
      "message": "unsupported file type: undefined",
      "stack":
          TypeError: unsupported file type: undefined
              at imageSize (file:///vercel-storage-blob-bug-repo/node_modules/.pnpm/[email protected]/node_modules/image-size/dist/index.mjs:985:9)
              at getImageSize (file:///vercel-storage-blob-bug-repo/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/payload/dist/uploads/getImageSize.js:20:12)
              at generateFileData (file:///vercel-storage-blob-bug-repo/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/payload/dist/uploads/generateFileData.js:142:32)
...

My first suspicion was that my image is corrupted, but my test image (a png) could sometimes be uploaded and sometimes not. I was able to reproduce it with multiple different images.

  • I was able to reproduce it both locally and when the app is deployed on Vercel.
  • I could not reproduce it when using clientUpload: false.

Please let me know if I can help any further to fix this bug.

Link to the code that reproduces this issue

https://github.com/FlavioReinhard/payload-vercel-blob-storage-repro

Reproduction Steps

  1. Create a vercel blob storage
  2. Provide the env variable BLOB_READ_WRITE_TOKEN in the .env file
  3. Start up payload: pnpm dev
  4. Upload an image to the media collection. Try it multiple times.

Which area(s) are affected? (Select all that apply)

plugin: storage-*

Environment Info

Binaries:
  Node: 18.20.7
  npm: 10.8.2
  Yarn: 1.22.22
  pnpm: 10.6.4
Relevant Packages:
  payload: 3.64.0
  next: 15.4.7
  @payloadcms/db-mongodb: 3.64.0
  @payloadcms/graphql: 3.64.0
  @payloadcms/next/utilities: 3.64.0
  @payloadcms/plugin-cloud-storage: 3.64.0
  @payloadcms/richtext-lexical: 3.64.0
  @payloadcms/storage-vercel-blob: 3.64.0
  @payloadcms/translations: 3.64.0
  @payloadcms/ui/shared: 3.64.0
  react: 19.1.0
  react-dom: 19.1.0
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:56 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8132
  Available memory (MB): 24576
  Available CPU cores: 10

FlavioReinhard avatar Nov 21 '25 23:11 FlavioReinhard

I digged some more. In my tests, the error occurred on this line: https://github.com/payloadcms/payload/blob/main/packages/payload/src/uploads/getImageSize.ts#L28

file had this structure:

{
  name: 'image.png',
  clientUploadContext: { prefix: '' },
  mimetype: 'image/png',
  size: 3067417,
  data: Buffer(15) [Uint8Array] [
    66, 108, 111,  98,  32,
    110, 111, 116,  32, 102,
    111, 117, 110, 100,  10
  ]
}

15 bytes of data seemed strange, as the file had size 3067417. data.toString() turned out to be: Blob not found.

As described above, the file was successfully uploaded to the blob storage by the client. I would assume that payload fetches the blob - as part of POST /api/media - in order to extract metadata and that call might have failed. Maybe this could be due to CDN propagation delay, but I'm just guessing.

FlavioReinhard avatar Nov 22 '25 00:11 FlavioReinhard

I wasn't able to reproduce this so far, you said that you were able to reproduce it around 30% of the time but now it happens less often, how less? I think I tried like 100 uploads and all of them were success.

r1tsuu avatar Nov 25 '25 15:11 r1tsuu

Hi @r1tsuu , thank you for having a look.

I think I found a more reliable flow to reproduce it:

  1. Ensure the media collection and the blob storage are empty.
  2. Create a PNG of >3MB or use the test file I added below (should be 3.7MB PNG) and create 14 copies of it.
  3. Start payload with a fresh build rm -rf .next && pnpm dev (not sure if necessary, but to be sure)
  4. Bulk Upload the 15 files (15/15 successful in my tests).
  5. Delete the 15 media documents in payload.
  6. Verify: Media Collection and the blob storage are empty again.
  7. Bulk Upload the same 15 files again.

I did this flow twice. In the first run 7/15 failed on step 7, in second run 13/15 failed, always with the error above.

I'm not sure if the error only happens on reupload of a deleted file, but it seems to make it more reproducable at least.

I hope this helps :)

Image

FlavioReinhard avatar Nov 26 '25 10:11 FlavioReinhard

I am running into this issue with the s3 adapter also, did you find any fixes?

Girbi avatar Dec 15 '25 15:12 Girbi