Bug Report
Package: @payloadcms/storage-vercel-blob@3.59.1
File: dist/staticHandler.js, lines 39-45
Description
When clientUploads: true and disablePayloadAccessControl: true, the staticHandler is invoked by addDataAndFileToRequest to fetch the uploaded file from Vercel Blob CDN so Payload can process it (generate thumbnails, etc.).
The handler calls head(fileUrl, { token }) which succeeds, then fetches the file from the CDN:
const response = await fetch(`${fileUrl}?${uploadedAtString}`, {
headers: { 'Cache-Control': 'no-store, no-cache, must-revalidate', Pragma: 'no-cache' }
});
const blob = await response.blob();
if (!blob) {
return new Response(null, { status: 204, statusText: 'No Content' });
}
const bodyBuffer = await blob.arrayBuffer();
return new Response(bodyBuffer, { headers, status: 200 });
The bug: There is no if (!response.ok) check. When the CDN returns 404 (or any non-200), the error page HTML is returned as a 200 response with the correct Content-Type header from head(). Payload then passes this HTML to sharp, which crashes with FileUploadError ("There was a problem while uploading the file").
Reproduction
- Enable
clientUploads: true and disablePayloadAccessControl: true on the Vercel Blob storage adapter
- Upload a file with consecutive spaces in the filename (e.g.
Geranium Body II 16 x 24.jpg) using client uploads
- The Blob API
head() confirms the file exists, but the CDN returns 404 for the URL — likely due to path normalization differences with consecutive %20 sequences
- sharp receives HTML error page content instead of image data and throws
FileUploadError
Expected Behavior
The handler should check response.ok and either retry, fall back to downloadUrl from the head() response, or return a proper error response.
Suggested Fix
const response = await fetch(`${fileUrl}?${uploadedAtString}`, { ... });
if (!response.ok) {
// Try the downloadUrl from head() as fallback
const fallbackResponse = await fetch(blobMetadata.downloadUrl);
if (!fallbackResponse.ok) {
return new Response(null, { status: response.status, statusText: 'Blob CDN fetch failed' });
}
const fallbackBuffer = await fallbackResponse.arrayBuffer();
return new Response(fallbackBuffer, { headers, status: 200 });
}
Workaround
We patched this with a Payload plugin that replaces the handler post-init — intercepting the static route and adding the response.ok check with a downloadUrl fallback.
Bug Report
Package:
@payloadcms/storage-vercel-blob@3.59.1File:
dist/staticHandler.js, lines 39-45Description
When
clientUploads: trueanddisablePayloadAccessControl: true, thestaticHandleris invoked byaddDataAndFileToRequestto fetch the uploaded file from Vercel Blob CDN so Payload can process it (generate thumbnails, etc.).The handler calls
head(fileUrl, { token })which succeeds, then fetches the file from the CDN:The bug: There is no
if (!response.ok)check. When the CDN returns 404 (or any non-200), the error page HTML is returned as a 200 response with the correctContent-Typeheader fromhead(). Payload then passes this HTML to sharp, which crashes withFileUploadError("There was a problem while uploading the file").Reproduction
clientUploads: trueanddisablePayloadAccessControl: trueon the Vercel Blob storage adapterGeranium Body II 16 x 24.jpg) using client uploadshead()confirms the file exists, but the CDN returns 404 for the URL — likely due to path normalization differences with consecutive%20sequencesFileUploadErrorExpected Behavior
The handler should check
response.okand either retry, fall back todownloadUrlfrom thehead()response, or return a proper error response.Suggested Fix
Workaround
We patched this with a Payload plugin that replaces the handler post-init — intercepting the static route and adding the
response.okcheck with adownloadUrlfallback.