Skip to content

fix(copy): return 400 when /copy body is not form-encoded - #275

Merged
kptdobe merged 1 commit into
mainfrom
fix/copy-bad-content-type-2026-05-07
May 7, 2026
Merged

kptdobe merged 1 commit into
mainfrom
fix/copy-bad-content-type-2026-05-07

Conversation

@kptdobe

@kptdobe kptdobe commented May 7, 2026

Copy link
Copy Markdown
Contributor

Why

Today's da-admin daily log review (24h ending 2026-05-07) surfaced 5 production POST 500s on /copy/scdemos/demo[/about-us.html], every one with the same unhandled exception:

TypeError: Unrecognized Content-Type header value. FormData can only parse the following MIME types: multipart/form-data, application/x-www-form-urlencoded

Coralogix breakdown (filter $d.ScriptName == 'da-admin' AND $d.Outcome == 'exception'):

ExceptionName ExceptionMessage hits
TypeError Unrecognized Content-Type header value. FormData can only parse the following MIME types: multipart/form-data, application/x-www-form-urlencoded 5

Root cause: src/helpers/copy.js calls await req.formData() unguarded. Cloudflare workers' FormData parser throws synchronously on unsupported MIME types, the throw bubbles into the worker runtime, and the client gets a 500 instead of a 4xx.

What

  • Wrap req.formData() in try/catch and return the existing { error } shape with status 400 + a clear message.
  • Add a unit test that simulates the production TypeError and asserts the handler returns 400 with a Content-Type error message. Test fails on main, passes after the fix.
const BAD_CONTENT_TYPE_ERROR = {
  body: JSON.stringify({ error: 'Invalid Content-Type. Expected multipart/form-data or application/x-www-form-urlencoded.' }),
  status: 400,
};

let formData;
try {
  formData = await req.formData();
} catch {
  return { error: BAD_CONTENT_TYPE_ERROR };
}

The route layer (src/routes/copy.js) already does if (details.error) return details.error;, so no route changes are needed.

Verification

$ npm test -- --grep "Copy Route"
  Copy Route
    ✔ Test copyHandler with permissions
    ✔ Test copyHandler returns 400 when request body is not form-encoded
    ✔ Test copyHandler - no destination provided

  3 passing

copy.js helper coverage: 100% statements, 81.81% branches.

npx eslint src/helpers/copy.js test/routes/copy.test.js → clean.

Out of scope

The same unguarded req.formData() pattern exists in move.js, source.js, delete.js, rename.js, kv/put.js. None of them surfaced in today's logs, so this PR scopes to /copy only — fix the rest lazily as they appear in future daily reviews.

…-encoded

COR-1 daily review (2026-05-07) surfaced 5 production POST 500s on
/copy/scdemos/demo[/about-us.html] with unhandled:

    TypeError: Unrecognized Content-Type header value. FormData can only
    parse the following MIME types: multipart/form-data,
    application/x-www-form-urlencoded

Cloudflare's req.formData() throws synchronously on unsupported MIME
types. The throw was bubbling out of the worker as a 500. Wrap it in
try/catch and return a structured 400 via the existing { error } shape.

Coralogix query (last 24h):

    source logs last 24h
    | filter \$d.ScriptName == 'da-admin'
    | filter \$d.Outcome == 'exception'

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@codecov

codecov Bot commented May 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@kptdobe
kptdobe requested a review from bosschaert May 7, 2026 13:12
@kptdobe
kptdobe merged commit a951f0c into main May 7, 2026
6 checks passed
@kptdobe
kptdobe deleted the fix/copy-bad-content-type-2026-05-07 branch May 7, 2026 13:25
adobe-bot pushed a commit that referenced this pull request May 7, 2026
## [1.7.3](v1.7.2...v1.7.3) (2026-05-07)

### Bug Fixes

* **copy:** return 400 instead of 500 when /copy POST body is not form-encoded ([#275](#275)) ([a951f0c](a951f0c))
@adobe-bot

Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 1.7.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants