diff --git a/.changeset/fix-blob-client-token-error-message.md b/.changeset/fix-blob-client-token-error-message.md new file mode 100644 index 000000000..e28d28a4f --- /dev/null +++ b/.changeset/fix-blob-client-token-error-message.md @@ -0,0 +1,11 @@ +--- +"@vercel/blob": patch +--- + +fix(blob): include HTTP status in error when client token retrieval fails + +When `upload()` fails to retrieve a client token from `handleUploadUrl` +(e.g. the route returns 401, 403, or 500), the error message now includes +the HTTP status code and status text to help with debugging. + +Closes #488 diff --git a/packages/blob/src/client.browser.test.ts b/packages/blob/src/client.browser.test.ts index d86f29c9d..348a2a414 100644 --- a/packages/blob/src/client.browser.test.ts +++ b/packages/blob/src/client.browser.test.ts @@ -163,6 +163,25 @@ describe('client', () => { }, ); }); + + it('throws with HTTP status when handleUploadUrl returns an error', async () => { + jest.spyOn(undici, 'fetch').mockImplementation( + jest.fn().mockResolvedValueOnce({ + status: 403, + statusText: 'Forbidden', + ok: false, + }), + ); + + await expect( + upload('foo.txt', 'Test file data', { + access: 'public', + handleUploadUrl: '/api/upload', + }), + ).rejects.toThrow( + 'Vercel Blob: Failed to retrieve the client token: 403 Forbidden', + ); + }); }); describe('multipart upload', () => { diff --git a/packages/blob/src/client.ts b/packages/blob/src/client.ts index 8c7eb12f1..d3eb5e658 100644 --- a/packages/blob/src/client.ts +++ b/packages/blob/src/client.ts @@ -698,7 +698,9 @@ async function retrieveClientToken(options: { }); if (!res.ok) { - throw new BlobError('Failed to retrieve the client token'); + throw new BlobError( + `Failed to retrieve the client token: ${res.status} ${res.statusText}`, + ); } try {