OpenAPI plugin uses nullable: true which is invalid in OpenAPI 3.1 #2508

Closed
opened 2026-03-13 10:00:10 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @hai-trung-le on GitHub (Dec 11, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

The official OpenAPI plugin hardcode its schema version to be OpenAPI 3.1.1. However, It converts ZodOptional types to a JSON object with "nullable": true

15232f142b/packages/better-auth/src/plugins/open-api/generator.ts (L194-L201)

and some API endpoints with manual OpenAPI documentation do this as well. This is only valid in OpenAPI 3.0; in OpenAPI 3.1, the correct way is either using an array of types

"type": ["string", "null"]

or using oneOf

"oneOf": {
  {
    "type": "string"
  },
  {
    "type": "null"
  }
}

We can either change how nullable properties are described or change OpenAPI version to 3.0 (while we're at it, I feel like the OpenAPI info should be customizable as well):

15232f142b/packages/better-auth/src/plugins/open-api/generator.ts (L529-L534)

Current vs. Expected behavior

OpenAPI schema marks nullable properties correctly.

What version of Better Auth are you using?

1.4.5

System info

{
  "system": {
    "platform": "win32",
    "arch": "x64",
    "version": "Windows 10 Pro"
  },
  "node": {
    "version": "v24.11.1",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.7.0"
  },
  "frameworks": [
    {
      "name": "next",
      "version": "^15.5.7"
    },
    {
      "name": "react",
      "version": "^19.2.1"
    }
  ],
  "databases": null,
  "betterAuth": {
    "version": "^1.4.5",
    "config": null
  }
}

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
  plugins: [
    bearer(),
    openAPI(),
  ],
});

Additional context

No response

Originally created by @hai-trung-le on GitHub (Dec 11, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce The official OpenAPI plugin hardcode its schema version to be OpenAPI 3.1.1. However, It converts `ZodOptional` types to a JSON object with `"nullable": true` https://github.com/better-auth/better-auth/blob/15232f142bf68b07594404b5425d2c99e4f55849/packages/better-auth/src/plugins/open-api/generator.ts#L194-L201 and some API endpoints with manual OpenAPI documentation do this as well. This is only valid in OpenAPI 3.0; in OpenAPI 3.1, the correct way is either using an array of types ``` "type": ["string", "null"] ``` or using `oneOf` ```json "oneOf": { { "type": "string" }, { "type": "null" } } ``` We can either change how nullable properties are described or change OpenAPI version to 3.0 (while we're at it, I feel like the OpenAPI info should be customizable as well): https://github.com/better-auth/better-auth/blob/15232f142bf68b07594404b5425d2c99e4f55849/packages/better-auth/src/plugins/open-api/generator.ts#L529-L534 ### Current vs. Expected behavior OpenAPI schema marks nullable properties correctly. ### What version of Better Auth are you using? 1.4.5 ### System info ```bash { "system": { "platform": "win32", "arch": "x64", "version": "Windows 10 Pro" }, "node": { "version": "v24.11.1", "env": "development" }, "packageManager": { "name": "npm", "version": "11.7.0" }, "frameworks": [ { "name": "next", "version": "^15.5.7" }, { "name": "react", "version": "^19.2.1" } ], "databases": null, "betterAuth": { "version": "^1.4.5", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, plugins: [ bearer(), openAPI(), ], }); ``` ### Additional context _No response_
GiteaMirror added the plugin label 2026-03-13 10:00:10 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Dec 11, 2025):

[tag @better-auth-agent if you would like an answer from the Agent]

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Dec 11, 2025): [tag @better-auth-agent if you would like an answer from the Agent] _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@dosubot[bot] commented on GitHub (Dec 11, 2025):

Hi @hai-trung-le! I'm Dosu and I’m helping the better-auth team.

You're right—Better Auth's OpenAPI plugin currently hardcodes the schema version to 3.1.1 but still emits nullable properties as "nullable": true, which is not valid in OpenAPI 3.1. In 3.1, nullability should be expressed as "type": ["string", "null"] or with a oneOf schema, not with the nullable keyword. This affects both generated and some hand-written endpoint schemas, leading to validation and codegen issues in tools like Orval and others (source).

The root of the problem is in the OpenAPI plugin's generator, where ZodOptional types are converted to schemas with nullable: true (source). The OpenAPI version and info fields are also hardcoded and not currently configurable.

There are several related issues and PRs confirming this bug and its impact (#6250, #6537, #6540). Some fixes have been attempted, but many still use nullable: true, which only works for OpenAPI 3.0, not 3.1.

Until a permanent fix lands, the recommended workaround is to patch the generated OpenAPI schema after generation—replace nullable: true with the correct OpenAPI 3.1 structure, and fix any misplaced required arrays if needed (source). Making the OpenAPI version and info configurable would also help users target the correct spec for their tooling.

If you need an example of how to patch the schema or want to track the status of a permanent fix, see the linked issues and PRs above.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Dec 11, 2025): <!-- Greeting --> Hi @hai-trung-le! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> You're right—Better Auth's OpenAPI plugin currently hardcodes the schema version to 3.1.1 but still emits nullable properties as `"nullable": true`, which is not valid in OpenAPI 3.1. In 3.1, nullability should be expressed as `"type": ["string", "null"]` or with a `oneOf` schema, not with the `nullable` keyword. This affects both generated and some hand-written endpoint schemas, leading to validation and codegen issues in tools like Orval and others ([source](https://github.com/better-auth/better-auth/blob/3cb5ded4c7eecfc57b47cceb7b43084d5e491ed1/packages/better-auth/src/plugins/open-api/generator.ts#L122-L571)). The root of the problem is in the OpenAPI plugin's generator, where ZodOptional types are converted to schemas with `nullable: true` ([source](https://github.com/better-auth/better-auth/blob/3cb5ded4c7eecfc57b47cceb7b43084d5e491ed1/packages/better-auth/src/plugins/open-api/generator.ts#L122-L571)). The OpenAPI version and info fields are also hardcoded and not currently configurable. There are several related issues and PRs confirming this bug and its impact ([#6250](https://github.com/better-auth/better-auth/issues/6250), [#6537](https://github.com/better-auth/better-auth/issues/6537), [#6540](https://github.com/better-auth/better-auth/pull/6540)). Some fixes have been attempted, but many still use `nullable: true`, which only works for OpenAPI 3.0, not 3.1. Until a permanent fix lands, the recommended workaround is to patch the generated OpenAPI schema after generation—replace `nullable: true` with the correct OpenAPI 3.1 structure, and fix any misplaced `required` arrays if needed ([source](https://github.com/better-auth/better-auth/issues/6250)). Making the OpenAPI version and info configurable would also help users target the correct spec for their tooling. If you need an example of how to patch the schema or want to track the status of a permanent fix, see the linked issues and PRs above. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/a9ddcd23-c8a8-410a-a0ef-21386d13d295?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/a9ddcd23-c8a8-410a-a0ef-21386d13d295?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/a9ddcd23-c8a8-410a-a0ef-21386d13d295?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/a9ddcd23-c8a8-410a-a0ef-21386d13d295?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/a9ddcd23-c8a8-410a-a0ef-21386d13d295?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/a9ddcd23-c8a8-410a-a0ef-21386d13d295?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/a9ddcd23-c8a8-410a-a0ef-21386d13d295?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=You%27re%20right%E2%80%94Better%20Auth%27s%20OpenAPI%20plugin%20currently%20hardcodes%20the%20schema%20version%20to%203.1.1%20but%20still%20emits%20nullable%20properties%20as%20%60%22nullable%22%3A%20true%60%2C%20which%20is%20not%20valid%20in%20OpenAPI%203.1.%20In%203.1%2C%20nullability%20should%20be%20expressed%20as%20%60%22type%22%3A%20%5B%22string%22%2C%20%22null%22%5D%60%20or%20with%20a%20%60oneOf%60%20schema%2C%20not%20with%20the%20%60nullable%60%20keyword.%20This%20affects%20both%20generated%20and%20some%20hand-written%20endpoint%20schemas%2C%20leading%20to%20validation%20and%20codegen%20issues%20in%20tools%20like%20Orval%20and%20others%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/blob/3cb5ded4c7eecfc57b47cceb7b43084d5e491ed1/packages/better-auth/src/plugins/open-api/generator.ts%23L122-L571%29%29.%0A%0AThe%20root%20of%20the%20problem%20is%20in%20the%20OpenAPI%20plugin%27s%20generator%2C%20where%20ZodOptional%20types%20are%20converted%20to%20schemas%20with%20%60nullable%3A%20true%60%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/blob/3cb5ded4c7eecfc57b47cceb7b43084d5e491ed1/packages/better-auth/src/plugins/open-api/generator.ts%23L122-L571%29%29.%20The%20OpenAPI%20version%20and%20info%20fields%20are%20also%20hardcoded%20and%20not%20currently%20configurable.%0A%0AThere%20are%20several%20related%20issues%20and%20PRs%20confirming%20this%20bug%20and%20its%20impact%20%28%5B%236250%5D%28https%3A//github.com/better-auth/better-auth/issues/6250%29%2C%20%5B%236537%5D%28https%3A//github.com/better-auth/better-auth/issues/6537%29%2C%20%5B%236540%5D%28https%3A//github.com/better-auth/better-auth/pull/6540%29%29.%20Some%20fixes%20have%20been%20attempted%2C%20but%20many%20still%20use%20%60nullable%3A%20true%60%2C%20which%20only%20works%20for%20OpenAPI%203.0%2C%20not%203.1.%0A%0AUntil%20a%20permanent%20fix%20lands%2C%20the%20recommended%20workaround%20is%20to%20patch%20the%20generated%20OpenAPI%20schema%20after%20generation%E2%80%94replace%20%60nullable%3A%20true%60%20with%20the%20correct%20OpenAPI%203.1%20structure%2C%20and%20fix%20any%20misplaced%20%60required%60%20arrays%20if%20needed%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/6250%29%29.%20Making%20the%20OpenAPI%20version%20and%20info%20configurable%20would%20also%20help%20users%20target%20the%20correct%20spec%20for%20their%20tooling.%0A%0AIf%20you%20need%20an%20example%20of%20how%20to%20patch%20the%20schema%20or%20want%20to%20track%20the%20status%20of%20a%20permanent%20fix%2C%20see%20the%20linked%20issues%20and%20PRs%20above.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/6691)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2508