Skip to content

fix: throw error when Content-Type is invalid#7036

Open
aviu16 wants to merge 2 commits intoexpressjs:masterfrom
aviu16:fix/content-type-false-literal
Open

fix: throw error when Content-Type is invalid#7036
aviu16 wants to merge 2 commits intoexpressjs:masterfrom
aviu16:fix/content-type-false-literal

Conversation

@aviu16
Copy link

@aviu16 aviu16 commented Feb 15, 2026

Summary

Fixes #7034

When calling res.set('Content-Type', value) where value is not a valid MIME type (e.g., 'some-custom-type'), mime.contentType() returns false. Previously, this false value was coerced to the literal string "false" and set as the Content-Type header.

Changes

This PR modifies res.set() in lib/response.js to throw a TypeError when mime.contentType() returns false, making the error explicit and easier to catch during development.

// Before (silently sets header to "false")
res.set('Content-Type', 'some-custom-type');
// => Content-Type: false

// After (throws TypeError)
res.set('Content-Type', 'some-custom-type');
// => TypeError: invalid content type

Rationale

As noted by @krzysdz in #7034, the Content-Type header must contain a valid media type with a / separator (per RFC 9110). Silently setting the header to "false" creates invalid HTTP responses that are harder to debug.

This change aligns with the existing TypeError thrown when Content-Type is set to an Array (line 674).

Test plan

  • ✅ All existing tests pass (npm test - 1244 passing)
  • ✅ Manually verified that invalid Content-Type now throws TypeError
  • ✅ Verified that valid Content-Types still work correctly (e.g., application/json, text/html)

when you call res.set('Content-Type', value) with something thats not a
real MIME type, mime.contentType() returns false and that false was getting
coerced to the string "false" and set as the header. now it throws a
TypeError instead.

fixes expressjs#7034
@aviu16 aviu16 force-pushed the fix/content-type-false-literal branch from 329913c to 0d3809c Compare February 15, 2026 23:48
@aviu16
Copy link
Author

aviu16 commented Feb 17, 2026

friendly ping: happy to adjust anything here if needed.

@aviu16
Copy link
Author

aviu16 commented Feb 17, 2026

added context on expected behavior: mime.contentType() can return false for invalid input, so this change throws a TypeError early instead of passing an invalid value into setHeader. happy to add/adjust tests if you want coverage around this branch.

@aviu16
Copy link
Author

aviu16 commented Feb 17, 2026

added regression coverage in test/res.set.js.\nnew case asserts invalid Content-Type input returns 500 with TypeError invalid content type.\n\nran locally: npm test -- test/res.set.js\nresult: passing.

@aviu16
Copy link
Author

aviu16 commented Feb 22, 2026

Friendly bump on this PR. When maintainers have a moment, could someone please take a look? Happy to make any requested changes quickly. Thanks!

@krzysdz
Copy link
Contributor

krzysdz commented Feb 22, 2026

It has not been decided yet what we want to do with the issue - see #7034 (comment). It's hard to review PRs that "solve" issues when it has not been agreed what is/should be the correct behaviour.

Copy link

@erdinccurebal erdinccurebal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This addresses the same underlying issue as #7035mime.contentType() returning false for unknown types — but takes a stricter approach by throwing a TypeError.

A few thoughts:

  1. Breaking change concern: Existing apps that set custom/non-standard Content-Type values (e.g. res.set('Content-Type', 'custom-type')) would start throwing. This could break production code on upgrade.

  2. Error message: 'invalid content type' could be more descriptive — e.g. 'Invalid Content-Type "' + value + '"' so the developer immediately knows which value caused the issue.

  3. Comparison with #7035: PR #7035 takes a more permissive approach (mime.contentType(value) || value), preserving the original value when the lookup fails. That approach is more backwards-compatible but less strict.

I'd lean toward #7035's approach being safer for a patch release, since throwing is a breaking behavior change. But if the maintainers prefer strictness, this approach is cleaner.

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.

res.set('Content-Type') silently sets header to literal string 'false' for unknown types

3 participants