Skip to content

fix(cloudflare): lazy-init S3 client to support dev mode without R2 creds#489

Open
zhuzhuyule wants to merge 2 commits intomasterfrom
fix/cf-upload-s3-client-lazy-init
Open

fix(cloudflare): lazy-init S3 client to support dev mode without R2 creds#489
zhuzhuyule wants to merge 2 commits intomasterfrom
fix/cf-upload-s3-client-lazy-init

Conversation

@zhuzhuyule
Copy link
Copy Markdown
Contributor

Summary

  • Fix accessKeyId is a required option crash on /uploads/presign when the worker is deployed with ENVIRONMENT=development but without R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY secrets set
  • Lazy-construct the AwsClient only inside the else branch where presigned-direct-to-R2 upload actually needs it
  • Add wrangler.staging.toml / wrangler.local.toml to cloudflare/.gitignore so per-environment configs don't get committed

Background

Verified during a fresh CF Workers deploy of media-kit to a staging account that intentionally avoided creating R2 S3 API tokens (using `ENVIRONMENT=development` to keep upload mode = proxy-put). The dev-mode branch in `upload.ts` is supposed to skip the S3 path entirely, but `createS3Client(c.env)` was called unconditionally on line 69, causing `aws4fetch` to throw before reaching the dev/prod branch.

Test plan

  • Deploy to staging with `ENVIRONMENT=development` and no R2 S3 secrets
  • Login via DID Connect, upload a small image through admin UI → success
  • Verify multipart upload (>= 100MB) still works in non-dev mode (out of scope for this fix — multipart routes still need R2 creds)

Known limitations not addressed by this PR

`/uploads/multipart/part-url` (line 356) and `/uploads/multipart/status` (line 443) still construct `createS3Client` unconditionally. They only trigger for files >= 100MB so dev-mode small-file uploads are unaffected. Suggest a follow-up PR to either lazy-init those too with a clear error, or add a `proxy-put` style fallback for multipart parts.

…reds

createS3Client(c.env) was called unconditionally at the top of the
/uploads/presign handler, which throws "accessKeyId is a required option"
when R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY are not set. The dev-mode
proxy-put branch is supposed to avoid the S3 path entirely, but the
upfront construction made dev-mode upload impossible without S3 creds.

Move the createS3Client call into the else branch so it only runs in
non-dev mode (where presigned direct-to-R2 upload is actually used).
This unblocks staging deployments that intentionally run with
ENVIRONMENT=development to avoid creating R2 S3 API tokens.

Note: multipart upload routes (/uploads/multipart/part-url and
/uploads/multipart/status) still construct the S3 client unconditionally.
Those paths trigger only for files >= 100MB, so this fix is sufficient
for the common single-file upload flow on staging.
….toml

These per-environment wrangler config files are local: they contain
environment-specific D1/R2 ids, KV namespace ids and service binding
targets that differ per Cloudflare account, and should never be
committed to the upstream repo. The tracked wrangler.toml stays as the
template; operators copy it to wrangler.staging.toml / wrangler.local.toml
and fill in real values for their account.
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 11, 2026

Image description AIGNE Framework

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant