#7038·fastify

put can reach route handler if no content type and no body is given, with body being undefined

Author: barbeque-squaredCreated Sep 18, 2026Updated Sep 21, 2026

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

5.12.5

Plugin version

No response

Node.js version

v26.8.2

Operating system

Linux

Operating system version (i.e. 20.04, 11.3, 10)

Archlinux

Description

If a route has a schema, and that schema defines specific content-types (ie, not the catch-all schema if you just do { body: { type: ... }}), then if you:

  • do a PUT request (probably also on POST/PATCH but didn't test this)
  • without the Content-Type header
  • also without the body

then it 'passes' validation and gets into the route handler. this creates a really strange situation where you have to start checking for undefined, even if according to the typing it can never be undefined at that point (I can't figure out what exactly causes it to choose strong typing vs unknown, but it's not super relevant right now)

if you clone the MRE repo, npm ci, npm start and look at the logs for request 3, 4, 5 + 6 (the first two are for a different issue, ignore those here):

  • no content type but it has a body = 415 (seems fine to me)
  • content type but it doesn't have a body = 400 (also seems fine to me)
  • no content type and also no body = it gets into the route handler with body: undefined which I'm not sure how it does that from the schema

bizarrely, if you just use the catch-all then it will 4xx on that last one, but not if you use content types, and I'm not sure why. The documentation does have a warning about needing to define for all content types, but the weird split between application/json and text/plain in the MRE is the only way I've ever been able to have application/json requests also allow booleans, strings, numbers etc, which the catch-all doesn't handle (you get errors about it needing to match exactly one of oneOf, and even if you send "true" it will still coerce it to a boolean)

it has been like this since at least 5.8.0 (I didn't test with older versions. it's possible this issue is a "duplicate" of 6597, I didn't put the # in front of it because that was labeled as AI spam)

Link to code that reproduces the bug

https://github.com/barbeque-squared/fastify-body-undefined

Expected Behavior

The request is rejected, probably with a 400 or 415. If it is intended behaviour, could we get an example schema of how we can still catch this case, because currently, this is creating places in production codebases where something that according to typescript can absolutely never be undefined turns out to be undefined after all