From 0ac550c039dcb7023cfff60fabb6c8f1f955cd7d Mon Sep 17 00:00:00 2001 From: Strtus Date: Tue, 19 May 2026 10:54:33 +0800 Subject: [PATCH] Fix client-side Vercel Blob fallback never executing HAS_VERCEL_BLOB_STORAGE depends on BLOB_READ_WRITE_TOKEN which is a server-only env var (not NEXT_PUBLIC_*), so it evaluates to false in the browser. When the R2 presigned-URL PUT fails (e.g. due to missing CORS on the R2 bucket), the fallback branch was unreachable and the original "Failed to fetch" error propagated to the UI. vercelBlobUploadFromClient works client-side because it obtains the token via a server round-trip to handleUploadUrl, so try it unconditionally as a fallback. Co-authored-by: Cursor --- src/platforms/storage/index.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/platforms/storage/index.ts b/src/platforms/storage/index.ts index b11d8e43..59dab5cc 100644 --- a/src/platforms/storage/index.ts +++ b/src/platforms/storage/index.ts @@ -160,12 +160,15 @@ export const uploadFileFromClient = async ( try { return await uploadFromClientViaPresignedUrl(file, fileName); } catch (error) { - // Fall back to Vercel Blob when configured, so uploads stay available - // even if third-party object storage is temporarily unreachable. - if (HAS_VERCEL_BLOB_STORAGE) { - return vercelBlobUploadFromClient(file, fileName); + // HAS_VERCEL_BLOB_STORAGE relies on BLOB_READ_WRITE_TOKEN which is a + // server-only variable (not NEXT_PUBLIC_*), so it is always false in + // the browser. vercelBlobUploadFromClient only needs the server-side + // token via handleUploadUrl, so try it unconditionally as a fallback. + try { + return await vercelBlobUploadFromClient(file, fileName); + } catch { + throw error; } - throw error; } }