fix(s3): default S3_REGION to us-east-1 instead of empty string (#495)

The AWS SDK throws "Region is missing" when S3Client is constructed
with an empty-string region, so any S3 feature (avatars, attachments,
presigned URL generation) is silently broken when S3_REGION is unset
— even though .env.example ships it unset and env.ts declares it
optional. The schema and the runtime disagreed about whether the var
was required.

Default to "us-east-1" in createS3Client. S3-compatible providers
(MinIO, Backblaze B2, R2, DigitalOcean Spaces, Wasabi) ignore the
region entirely; real AWS S3 users should set S3_REGION explicitly
to their bucket's actual region (clarified in .env.example).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Meinhold
2026-05-17 07:56:48 +10:00
committed by GitHub
parent d9157b6218
commit f801d2a7eb
2 changed files with 9 additions and 3 deletions

View File

@@ -23,8 +23,8 @@ SMTP_REJECT_UNAUTHORIZED= # set to "false" to accept invalid certs
NEXT_PUBLIC_DISABLE_EMAIL=
# S3 storage (optional)
S3_REGION=
S3_ENDPOINT=
S3_REGION= # required for AWS S3 (e.g. us-east-1); ignored by most S3-compatible providers — defaults to us-east-1 if unset
S3_ENDPOINT= # set for S3-compatible providers (MinIO, R2, Spaces, etc.); leave blank for AWS S3
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_FORCE_PATH_STYLE=

View File

@@ -16,8 +16,14 @@ export function createS3Client() {
}
: undefined;
// The AWS SDK throws "Region is missing" if region is undefined or
// empty string at S3Client construction. Default to "us-east-1" so
// S3-compatible providers (MinIO, Backblaze B2, R2, Spaces, Wasabi)
// that don't care about region work without forcing operators to
// set a meaningless value. Real AWS S3 users should still set
// S3_REGION explicitly to their bucket's actual region.
return new S3Client({
region: process.env.S3_REGION ?? "",
region: process.env.S3_REGION ?? "us-east-1",
endpoint: process.env.S3_ENDPOINT ?? "",
forcePathStyle: process.env.S3_FORCE_PATH_STYLE === "true",
credentials,