Skip to content

requestBody.required not set to true when route has body schema with only optional properties #894

@khokm

Description

@khokm

Fastify version

5.5.0

Plugin version

9.5.1

Node.js version

22.14.0

Operating system

Windows 10

Description

When a route has a schema.body defined, Fastify requires that the request includes a body (at least {}), even if all properties inside that body are optional.

However, the OpenAPI schema generated by @fastify/swagger does not correctly reflect this requirement. Currently, requestBody.required is set to true only when there are required properties inside the object. If the object has only optional properties, then requestBody.required is omitted.

Example:

import { fastifySwagger } from "@fastify/swagger";
import { JsonSchemaToTsProvider } from "@fastify/type-provider-json-schema-to-ts";
import { fastify } from "fastify";

const server = fastify().withTypeProvider<JsonSchemaToTsProvider>();

(async function () {
  await server.register(fastifySwagger, {
    openapi: {
      openapi: "3.1.0",
    },
  });

  server.put(
    "/",
    {
      schema: {
        body: {
          type: "object",
          properties: {
            hello: { type: "string" },
          },
        },
      },
    },
    async (req) => {
      console.log(req.body.hello?.length); // hello is optional but the body is not.
    },
  );

  await server.ready();

  const swagger = server.swagger();
})();

Expected OpenAPI output:

"requestBody": {
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "hello": { "type": "string" }
        }
      }
    }
  }
}

Actual OpenAPI output:

"requestBody": {
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "hello": { "type": "string" }
        }
      }
    }
  }
}

In Fastify, the body itself is required if schema.body is defined.

The generated OpenAPI spec incorrectly marks it as optional, which can mislead client code generators and API consumers.

Expected Behavior

If a route has schema.body, requestBody.required should always be set to true, regardless of whether any properties inside the body are required.

Current fix using transformObject

transformObject: (documentObject) => {
    assert("openapiObject" in documentObject);

    const { openapiObject } = documentObject;

    for (const pathKey in openapiObject.paths) {
        const pathItem = openapiObject.paths[pathKey];
        if (!pathItem) continue;

        for (const methodKey of Object.keys(pathItem) as Array<keyof typeof pathItem>) {
            const operation = pathItem[methodKey];

            if (!operation || typeof operation === "string") continue;
            if ("requestBody" in operation && operation.requestBody && "content" in operation.requestBody) {
                operation.requestBody.required = true;
            }
        }
    }

    return openapiObject;
},

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions