Three small correctness/consistency issues in the S3 provider. None is a live defect — grouping them so they can be cleaned up in one pass.
1. The NoSuchKey checks are dead code
exists and getInfo both test err instanceof S3.NoSuchKey, but both send a HeadObjectCommand, and NoSuchKey is not modelled on that operation. From the installed SDK:
@aws-sdk/client-s3/dist-types/commands/GetObjectCommand.d.ts:297 → @throws {@link NoSuchKey}
@aws-sdk/client-s3/dist-types/commands/HeadObjectCommand.d.ts:271 → @throws {@link NotFound}
So against real S3 a missing key surfaces as NotFound, never NoSuchKey. The err["$metadata"]?.httpStatusCode === 404 check is what actually catches it in both methods, which is why behaviour is correct today — the NoSuchKey arms are simply never taken.
This showed up while writing branch coverage: reaching those arms required hand-constructing new S3.NoSuchKey({} as any) and rejecting a mocked send with it. Nothing the HeadObjectCommand path can produce yields that type.
S3.NotFound is exported (@aws-sdk/client-s3/dist-types/models/errors.d.ts:131) and is the type those lines should name — or they can be dropped entirely in favour of the existing 404 check.
2. getInfo timestamp fallback differs from the other providers
lastModified: data.LastModified || new Date(), // S3
lastModified: properties.lastModified || new Date(0), // Azure
lastModified: metadata.updated ? new Date(metadata.updated) : new Date(0), // GCP
A missing timestamp reads as "modified right now" on S3/MinIO, and as the epoch everywhere else. The epoch is the safer signal — "unknown" should not look like "just changed", which can mislead any freshness or cache check downstream. Changing it to new Date(0) does not break the current spec, which asserts instanceof Date.
3. ConfigureAWS validates after doing the work
ConfigureAWS loads the SDK and constructs the S3Client before checking S3_BUCKET, so the missing-bucket throw comes after that work. ConfigureMinio validates all four of its env vars first. Purely cosmetic, but worth making consistent while the file is open.
Three small correctness/consistency issues in the S3 provider. None is a live defect — grouping them so they can be cleaned up in one pass.
1. The
NoSuchKeychecks are dead codeexistsandgetInfoboth testerr instanceof S3.NoSuchKey, but both send aHeadObjectCommand, andNoSuchKeyis not modelled on that operation. From the installed SDK:@aws-sdk/client-s3/dist-types/commands/GetObjectCommand.d.ts:297→@throws {@link NoSuchKey}@aws-sdk/client-s3/dist-types/commands/HeadObjectCommand.d.ts:271→@throws {@link NotFound}So against real S3 a missing key surfaces as
NotFound, neverNoSuchKey. Theerr["$metadata"]?.httpStatusCode === 404check is what actually catches it in both methods, which is why behaviour is correct today — theNoSuchKeyarms are simply never taken.This showed up while writing branch coverage: reaching those arms required hand-constructing
new S3.NoSuchKey({} as any)and rejecting a mockedsendwith it. Nothing theHeadObjectCommandpath can produce yields that type.S3.NotFoundis exported (@aws-sdk/client-s3/dist-types/models/errors.d.ts:131) and is the type those lines should name — or they can be dropped entirely in favour of the existing 404 check.2.
getInfotimestamp fallback differs from the other providersA missing timestamp reads as "modified right now" on S3/MinIO, and as the epoch everywhere else. The epoch is the safer signal — "unknown" should not look like "just changed", which can mislead any freshness or cache check downstream. Changing it to
new Date(0)does not break the current spec, which assertsinstanceof Date.3.
ConfigureAWSvalidates after doing the workConfigureAWSloads the SDK and constructs theS3Clientbefore checkingS3_BUCKET, so the missing-bucket throw comes after that work.ConfigureMiniovalidates all four of its env vars first. Purely cosmetic, but worth making consistent while the file is open.