From a19921d08fa7b9c8ea280564a14da9325014a332 Mon Sep 17 00:00:00 2001 From: Anders Semb Hermansen Date: Wed, 11 Jun 2025 14:04:25 +0200 Subject: [PATCH] fix(storage-s3): return error status 404 when file is not found instead of 500 (#11733) ### What? The s3 storage adapter returns a 500 internal server error when a file is not found. It's expected that it will return 404 when a file is not found. ### Why? The getObject function from aws s3 sdk does not return undefined when a blob is not found, but throws a NoSuchKey error: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-s3/Class/NoSuchKey/ ### How? Check if exception thrown is of type NoSuchKey and return a 404 in that case. Related discord discussion: https://discord.com/channels/967097582721572934/1350826594062696539/1350826594062696539 --- packages/storage-s3/src/staticHandler.ts | 9 ++++----- test/storage-s3/int.spec.ts | 5 +++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/storage-s3/src/staticHandler.ts b/packages/storage-s3/src/staticHandler.ts index 4c4fd47d68..016ce6ee1b 100644 --- a/packages/storage-s3/src/staticHandler.ts +++ b/packages/storage-s3/src/staticHandler.ts @@ -1,8 +1,8 @@ -import type * as AWS from '@aws-sdk/client-s3' import type { StaticHandler } from '@payloadcms/plugin-cloud-storage/types' import type { CollectionConfig, PayloadRequest } from 'payload' import type { Readable } from 'stream' +import * as AWS from '@aws-sdk/client-s3' import { GetObjectCommand } from '@aws-sdk/client-s3' import { getSignedUrl } from '@aws-sdk/s3-request-presigner' import { getFilePrefix } from '@payloadcms/plugin-cloud-storage/utilities' @@ -94,10 +94,6 @@ export const getHandler = ({ Key: key, }) - if (!object.Body) { - return new Response(null, { status: 404, statusText: 'Not Found' }) - } - const etagFromHeaders = req.headers.get('etag') || req.headers.get('if-none-match') const objectEtag = object.ETag @@ -138,6 +134,9 @@ export const getHandler = ({ status: 200, }) } catch (err) { + if (err instanceof AWS.NoSuchKey) { + return new Response(null, { status: 404, statusText: 'Not Found' }) + } req.payload.logger.error(err) return new Response('Internal Server Error', { status: 500 }) } finally { diff --git a/test/storage-s3/int.spec.ts b/test/storage-s3/int.spec.ts index 60c4a9431e..463724c867 100644 --- a/test/storage-s3/int.spec.ts +++ b/test/storage-s3/int.spec.ts @@ -110,6 +110,11 @@ describe('@payloadcms/storage-s3', () => { expect(response.headers.get('Content-Type')).toBe('image/png') }) + it('should return 404 when the file is not found', async () => { + const response = await restClient.GET(`/${mediaSlug}/file/missing.png`) + expect(response.status).toBe(404) + }) + describe('R2', () => { it.todo('can upload') })