Skip to content

Admin media upload probes signed upload URLs with R2 binding storage and returns NOT_SUPPORTED #2256

Description

@diogoascarneiro

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:

POST /_emdash/api/media

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

  1. 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" }),
    });
  2. Add the matching R2 binding in wrangler.jsonc:

    {
      "r2_buckets": [
        {
          "binding": "MEDIA",
          "bucket_name": "example-media"
        }
      ]
    }
  3. Deploy/run the site on Cloudflare Workers.

  4. Open /_emdash/admin and upload an image from the media library or an image field.

  5. 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."
  }
}

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions