You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
res.set('Content-Type') silently sets header to literal string 'false' for unknown types #7034
When calling res.set('Content-Type', value) where the value doesn't contain a / (like a bare extension or shorthand), mime.contentType(value) is used to resolve the full MIME type. However, if mime.contentType() returns false (for unrecognized types), the Content-Type header is set to the literal string "false" instead of keeping the original value.
Requesting / returns Content-Type: false in the response headers.
Root cause:
In res.set() (response.js), the Content-Type branch does:
if(field.toLowerCase()==='content-type'){if(Array.isArray(value)){thrownewTypeError('Content-Type cannot be set to an Array');}value=mime.contentType(value)// can return false!}this.setHeader(field,value);
When mime.contentType(value) returns false, the value false is passed to setHeader, which coerces it to the string "false".
Contrast with res.type() which handles this correctly:
mime.contentType() returns false only if the provided argument is not a valid mime type or a known file extension (list is in mime-db). The Content-Type header carries a media type, which MUST contain a "/" (see the linked RFC for exact definition).
I think that maybe Express should throw an error if mime.contentType() returns false, so that this mistake is easier to catch.
That’s a good catch. Honestly, I’m not sure what we should do here yet. I don’t really like the idea of throwing an error in this case (even though it seems logical).
What I do think we should do is document it. I have it on my TODO list to add it to the new page.
The question is whether we should silently ignore unrecognized types, warn, or throw. Silently ignoring could hide bugs. Maybe logging a warning and keeping the original value would be the safest approach:
constct=mime.contentType(type);if(ct){this.set('Content-Type',ct);}else{// Unrecognized shorthand, use the original value as-isthis.setHeader('Content-Type',type);}
After a brief review I'm of the opinion that this should error. It currently doesn't work, and some downstream code relies on Content-Type being valid (just
). If it's set to something invalid, it creates a harder to debug experience later. By throwing an error, you'll at least have a stack track to follow and fix.
Currently the behavior doesn't work at all, since it sets to false. So there shouldn't be anyone relying on this behavior successfully, but if there is changing it to a different header will also create surprises. IMO it's better to have a clear upgrade path for them.
Finally, I also advocate for adding a deprecation message to the behavior altogether, and removing in v6. We already have a clearer method, res.type, that can be used for this and IMO .set('content-type', 'x') being changed underneath you is a surprising behavior of the library.
Activity
fix: prevent Content-Type header from being set to 'false'
krzysdz commentedon Feb 14, 2026
mime.contentType()returnsfalseonly if the provided argument is not a valid mime type or a known file extension (list is inmime-db). TheContent-Typeheader carries a media type, which MUST contain a "/" (see the linked RFC for exact definition).I think that maybe Express should throw an error if
mime.contentType()returnsfalse, so that this mistake is easier to catch.fix: throw error when Content-Type is invalid
bjohansebas commentedon Feb 15, 2026
That’s a good catch. Honestly, I’m not sure what we should do here yet. I don’t really like the idea of throwing an error in this case (even though it seems logical).
What I do think we should do is document it. I have it on my TODO list to add it to the new page.
fix: throw error when Content-Type is invalid
fix: prevent res.set('Content-Type') from setting header to 'false'
fix: preserve original value when Content-Type is unrecognized
mahmoodhamdi commentedon Mar 15, 2026
The issue is in this path: res.set() -> mime.contentType() -> returns false -> header set to literal "false".
Looking at the code in lib/response.js, the contentType method calls mime.contentType() and sets whatever it returns without checking for false:
A simple guard would fix this:
The question is whether we should silently ignore unrecognized types, warn, or throw. Silently ignoring could hide bugs. Maybe logging a warning and keeping the original value would be the safest approach:
JiwaniZakir commentedon Mar 17, 2026
I think I see what's going on here. Going to put together a fix.
fix(res.set): prevent Content-Type from being set to 'false' for unkn…
blakeembrey commentedon Mar 31, 2026
After a brief review I'm of the opinion that this should error. It currently doesn't work, and some downstream code relies on
Content-Typebeing valid (justexpress/lib/utils.js
Lines 225 to 238 in e509919
Currently the behavior doesn't work at all, since it sets to
false. So there shouldn't be anyone relying on this behavior successfully, but if there is changing it to a different header will also create surprises. IMO it's better to have a clear upgrade path for them.Finally, I also advocate for adding a deprecation message to the behavior altogether, and removing in v6. We already have a clearer method,
res.type, that can be used for this and IMO.set('content-type', 'x')being changed underneath you is a surprising behavior of the library.fix(res.set): remove implicit mime lookup and charset injection for C…