Description
When uploading media in the EmDash admin on a Cloudflare Workers site configured with the Cloudflare R2 binding storage adapter, the admin first calls the signed upload URL endpoint:
POST /_emdash/api/media/upload-url
That endpoint returns a failed JSON response because R2 binding storage does not support signed upload URLs:
{
"success": false,
"error": {
"code": "NOT_SUPPORTED",
"message": "Storage does not support signed upload URLs. Use direct upload."
}
}
The admin then falls back to direct upload via:
In cases where the fallback succeeds, the upload still leaves an alarming failed request in DevTools and makes it look like media upload is broken. Since R2 binding storage is a known non-signed-upload adapter, I expected the admin either to skip the signed URL probe for that storage backend or to handle the fallback without surfacing a failed API call.
There also appears to be a possible side effect in the signed upload URL endpoint: it creates a pending media record before calling storage.getSignedUploadUrl(). For adapters that always throw NOT_SUPPORTED, each probe may create a temporary pending media row even though the upload is immediately retried through the direct upload path.
Steps to reproduce
-
Configure an EmDash site for Cloudflare Workers with R2 binding storage:
import emdash from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";
emdash({
storage: r2({ binding: "MEDIA" }),
});
-
Add the matching R2 binding in wrangler.jsonc:
-
Deploy/run the site on Cloudflare Workers.
-
Open /_emdash/admin and upload an image from the media library or an image field.
-
Observe the failed POST /_emdash/api/media/upload-url request returning NOT_SUPPORTED before the admin falls back to POST /_emdash/api/media.
Environment
- emdash version:
0.31.0
@emdash-cms/admin version: 0.31.0
@emdash-cms/cloudflare version: 0.31.0
- Node.js version:
v22.22.3
- Runtime: Cloudflare Workers
- Storage: Cloudflare R2 binding adapter,
r2({ binding: "MEDIA" })
- OS: macOS
Logs / error output
{
"success": false,
"error": {
"code": "NOT_SUPPORTED",
"message": "Storage does not support signed upload URLs. Use direct upload."
}
}
Description
When uploading media in the EmDash admin on a Cloudflare Workers site configured with the Cloudflare R2 binding storage adapter, the admin first calls the signed upload URL endpoint:
That endpoint returns a failed JSON response because R2 binding storage does not support signed upload URLs:
{ "success": false, "error": { "code": "NOT_SUPPORTED", "message": "Storage does not support signed upload URLs. Use direct upload." } }The admin then falls back to direct upload via:
In cases where the fallback succeeds, the upload still leaves an alarming failed request in DevTools and makes it look like media upload is broken. Since R2 binding storage is a known non-signed-upload adapter, I expected the admin either to skip the signed URL probe for that storage backend or to handle the fallback without surfacing a failed API call.
There also appears to be a possible side effect in the signed upload URL endpoint: it creates a pending media record before calling
storage.getSignedUploadUrl(). For adapters that always throwNOT_SUPPORTED, each probe may create a temporary pending media row even though the upload is immediately retried through the direct upload path.Steps to reproduce
Configure an EmDash site for Cloudflare Workers with R2 binding storage:
Add the matching R2 binding in
wrangler.jsonc:{ "r2_buckets": [ { "binding": "MEDIA", "bucket_name": "example-media" } ] }Deploy/run the site on Cloudflare Workers.
Open
/_emdash/adminand upload an image from the media library or an image field.Observe the failed
POST /_emdash/api/media/upload-urlrequest returningNOT_SUPPORTEDbefore the admin falls back toPOST /_emdash/api/media.Environment
0.31.0@emdash-cms/adminversion:0.31.0@emdash-cms/cloudflareversion:0.31.0v22.22.3r2({ binding: "MEDIA" })Logs / error output
{ "success": false, "error": { "code": "NOT_SUPPORTED", "message": "Storage does not support signed upload URLs. Use direct upload." } }