[GH-ISSUE #6250] OpenAPI plugin generates invalid schema for sign-in endpoint causing syntax errors in code generation tools #19089

Closed
opened 2026-04-15 17:52:47 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @viniciuspatzer on GitHub (Nov 24, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/6250

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Set up better-auth with the openAPI() plugin enabled
  2. Generate the OpenAPI schema using auth.api.generateOpenAPISchema()
  3. Export the schema to a JSON file and use it with a code generation tool like Orval
  4. The syntax error will occur when Orval attempts to parse the schema

Current vs. Expected behavior

Current behavior:
When using the OpenAPI schema generated by better-auth's openAPI() plugin with code generation tools like Orval, the following validation errors occur:

⚠️  SyntaxError: Swagger schema validation failed.

#/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema/properties/url/type must be equal to one of the allowed values
#/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema/properties/url must have required property '$ref'
#/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema/properties/url must match exactly one schema in oneOf
#/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema must have required property '$ref'
#/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema must match exactly one schema in oneOf
#/paths/~1api~1auth~1sign-in~1email/post/responses/200 must have required property '$ref'
#/paths/~1api~1auth~1sign-in~1email/post/responses/200 must match exactly one schema in oneOf

The generated schema for the /sign-in/email endpoint contains invalid schema definitions where the url property in the response has an invalid or missing type field, and the overall response schema structure doesn't properly comply with OpenAPI specification requirements.

Expected behavior:
The OpenAPI schema generated by auth.api.generateOpenAPISchema() should produce valid OpenAPI 3.0/3.1 compliant schemas that pass validation in standard tools. Specifically:

  • All properties should have valid type values
  • Response schemas should properly reference components or follow oneOf requirements correctly
  • The schema should be consumable by code generation tools like Orval

What version of Better Auth are you using?

1.4.1

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.3.0: Thu Jan  2 20:24:06 PST 2025; root:xnu-11215.81.4~3/RELEASE_ARM64_T8103",
    "release": "24.3.0",
    "cpuCount": 8,
    "cpuModel": "Apple M1",
    "totalMemory": "8.00 GB",
    "freeMemory": "0.18 GB"
  },
  "node": {
    "version": "v24.11.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.6.1"
  },
  "frameworks": [
    {
      "name": "fastify",
      "version": "^5.2.1"
    }
  ],
  "databases": [
    {
      "name": "postgres",
      "version": "^3.4.5"
    },
    {
      "name": "drizzle",
      "version": "^1.0.0-beta.1-c0277c0"
    }
  ],
  "betterAuth": {
    "version": "^1.4.1",
    "config": {
      "appName": "TBD",
      "baseURL": "[REDACTED]",
      "basePath": "/api/auth",
      "secret": "[REDACTED]",
      "trustedOrigins": [
        "*.local"
      ],
      "plugins": [
        {
          "name": "open-api",
          "config": {
            "id": "open-api",
            "endpoints": {}
          }
        }
      ],
      "emailAndPassword": {
        "enabled": true,
        "autoSignIn": true,
        "minPasswordLength": 4,
        "maxPasswordLength": 128,
        "requireEmailVerification": false
      },
      "user": {},
      "session": {
        "cookieCache": {
          "enabled": true,
          "maxAge": 2592000,
          "strategy": "jwt",
          "refreshCache": true,
          "version": "1"
        }
      },
      "account": {
        "accountLinking": {
          "enabled": false,
          "trustedProviders": [
            "email"
          ]
        }
      },
      "advanced": {
        "useSecureCookies": false,
        "disableCSRFCheck": true,
        "cookiePrefix": "app",
        "defaultCookieAttributes": {
          "httpOnly": false,
          "secure": false,
          "sameSite": "lax",
          "path": "/"
        },
        "crossSubDomainCookies": {
          "enabled": false
        },
        "database": {
          "generateId": false,
          "defaultFindManyLimit": 100
        },
        "ipAddress": {
          "disableIpTracking": false,
          "ipAddressHeaders": [
            "x-forwarded-for",
            "x-real-ip"
          ]
        }
      },
      "hooks": {},
      "rateLimit": {
        "enabled": false,
        "window": 60,
        "max": 100,
        "customRules": {
          "/sign-up/email": {
            "window": 3600,
            "max": 5
          },
          "/sign-in/email": {
            "window": 900,
            "max": 10
          },
          "/reset-password": {
            "window": 3600,
            "max": 3
          }
        },
        "storage": "memory"
      },
      "disabledPaths": [
        "/get-session",
        "/list-sessions",
        "/revoke-session",
        "/revoke-sessions",
        "/revoke-other-sessions",
        "/sign-in/social",
        "/link-social",
        "/unlink-account",
        "/list-accounts",
        "/change-email",
        "/delete-user",
        "/delete-user/callback",
        "/refresh-token",
        "/get-access-token",
        "/account-info",
        "/forget-password"
      ],
      "logger": {
        "disabled": false,
        "level": "info"
      },
      "experimental": {
        "joins": true
      }
    }
  }
}

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

Backend, Types, Documentation, Package

Additional context

  1. This issue has been present since before version 1.4
Originally created by @viniciuspatzer on GitHub (Nov 24, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/6250 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Set up better-auth with the openAPI() plugin enabled 2. Generate the OpenAPI schema using auth.api.generateOpenAPISchema() 3. Export the schema to a JSON file and use it with a code generation tool like Orval 4. The syntax error will occur when Orval attempts to parse the schema ### Current vs. Expected behavior **Current behavior:** When using the OpenAPI schema generated by better-auth's openAPI() plugin with code generation tools like Orval, the following validation errors occur: ```text ⚠️ SyntaxError: Swagger schema validation failed. #/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema/properties/url/type must be equal to one of the allowed values #/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema/properties/url must have required property '$ref' #/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema/properties/url must match exactly one schema in oneOf #/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema must have required property '$ref' #/paths/~1api~1auth~1sign-in~1email/post/responses/200/content/application~1json/schema must match exactly one schema in oneOf #/paths/~1api~1auth~1sign-in~1email/post/responses/200 must have required property '$ref' #/paths/~1api~1auth~1sign-in~1email/post/responses/200 must match exactly one schema in oneOf ``` The generated schema for the /sign-in/email endpoint contains invalid schema definitions where the url property in the response has an invalid or missing type field, and the overall response schema structure doesn't properly comply with OpenAPI specification requirements. **Expected behavior:** The OpenAPI schema generated by auth.api.generateOpenAPISchema() should produce valid OpenAPI 3.0/3.1 compliant schemas that pass validation in standard tools. Specifically: - All properties should have valid type values - Response schemas should properly reference components or follow oneOf requirements correctly - The schema should be consumable by code generation tools like Orval ### What version of Better Auth are you using? 1.4.1 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.3.0: Thu Jan 2 20:24:06 PST 2025; root:xnu-11215.81.4~3/RELEASE_ARM64_T8103", "release": "24.3.0", "cpuCount": 8, "cpuModel": "Apple M1", "totalMemory": "8.00 GB", "freeMemory": "0.18 GB" }, "node": { "version": "v24.11.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.6.1" }, "frameworks": [ { "name": "fastify", "version": "^5.2.1" } ], "databases": [ { "name": "postgres", "version": "^3.4.5" }, { "name": "drizzle", "version": "^1.0.0-beta.1-c0277c0" } ], "betterAuth": { "version": "^1.4.1", "config": { "appName": "TBD", "baseURL": "[REDACTED]", "basePath": "/api/auth", "secret": "[REDACTED]", "trustedOrigins": [ "*.local" ], "plugins": [ { "name": "open-api", "config": { "id": "open-api", "endpoints": {} } } ], "emailAndPassword": { "enabled": true, "autoSignIn": true, "minPasswordLength": 4, "maxPasswordLength": 128, "requireEmailVerification": false }, "user": {}, "session": { "cookieCache": { "enabled": true, "maxAge": 2592000, "strategy": "jwt", "refreshCache": true, "version": "1" } }, "account": { "accountLinking": { "enabled": false, "trustedProviders": [ "email" ] } }, "advanced": { "useSecureCookies": false, "disableCSRFCheck": true, "cookiePrefix": "app", "defaultCookieAttributes": { "httpOnly": false, "secure": false, "sameSite": "lax", "path": "/" }, "crossSubDomainCookies": { "enabled": false }, "database": { "generateId": false, "defaultFindManyLimit": 100 }, "ipAddress": { "disableIpTracking": false, "ipAddressHeaders": [ "x-forwarded-for", "x-real-ip" ] } }, "hooks": {}, "rateLimit": { "enabled": false, "window": 60, "max": 100, "customRules": { "/sign-up/email": { "window": 3600, "max": 5 }, "/sign-in/email": { "window": 900, "max": 10 }, "/reset-password": { "window": 3600, "max": 3 } }, "storage": "memory" }, "disabledPaths": [ "/get-session", "/list-sessions", "/revoke-session", "/revoke-sessions", "/revoke-other-sessions", "/sign-in/social", "/link-social", "/unlink-account", "/list-accounts", "/change-email", "/delete-user", "/delete-user/callback", "/refresh-token", "/get-access-token", "/account-info", "/forget-password" ], "logger": { "disabled": false, "level": "info" }, "experimental": { "joins": true } } } } ``` ### Which area(s) are affected? (Select all that apply) Backend, Types, Documentation, Package ### Additional context 1. This issue has been present since before version 1.4
GiteaMirror added the locked label 2026-04-15 17:52:47 -05:00
Author
Owner

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

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

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3568621536 --> @better-auth-agent[bot] commented on GitHub (Nov 24, 2025): tag @better-auth-agent if you would like an answer from the Agent <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@dosubot[bot] commented on GitHub (Nov 24, 2025):

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

This is a known issue: the OpenAPI plugin in Better Auth generates an invalid schema for the /sign-in/email endpoint, specifically because the url property in the 200 response is defined as "type": "null", "nullable": true, which is not allowed by OpenAPI 3.0/3.1 and causes validation/codegen failures in tools like Orval. The actual implementation returns url as a string or undefined, so the schema should use "type": "string", "nullable": true" instead. There are also broader issues with misplaced required arrays and missing $ref usage in some responses, which can break strict OpenAPI tooling. This bug is confirmed in v1.4.1 and earlier, and is tracked in issue #2097 and related discussions.

A permanent fix is pending in PR #2107, but it hasn't been merged yet.

Workaround:
After generating your OpenAPI schema, patch the relevant response like this:

const schema = await auth.api.generateOpenAPISchema();
const signInEmailResp = schema.paths?.["/sign-in/email"]?.post?.responses?.["200"]?.content?.["application/json"]?.schema;
if (signInEmailResp?.properties?.url) {
  signInEmailResp.properties.url.type = "string";
  signInEmailResp.properties.url.nullable = true;
}

If you encounter misplaced required arrays (inside properties instead of at the object level), move them up to be siblings of properties.

Monitor PR #2107 for a permanent fix. Until then, manual patching is the most reliable solution.

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

<!-- gh-comment-id:3568624793 --> @dosubot[bot] commented on GitHub (Nov 24, 2025): <!-- Greeting --> Hi @viniciuspatzer! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This is a known issue: the OpenAPI plugin in Better Auth generates an invalid schema for the `/sign-in/email` endpoint, specifically because the `url` property in the 200 response is defined as `"type": "null", "nullable": true`, which is not allowed by OpenAPI 3.0/3.1 and causes validation/codegen failures in tools like Orval. The actual implementation returns `url` as a string or undefined, so the schema should use `"type": "string", "nullable": true"` instead. There are also broader issues with misplaced `required` arrays and missing `$ref` usage in some responses, which can break strict OpenAPI tooling. This bug is confirmed in v1.4.1 and earlier, and is tracked in [issue #2097](https://github.com/better-auth/better-auth/issues/2097) and [related discussions](https://github.com/better-auth/better-auth/issues/5607). A permanent fix is pending in [PR #2107](https://github.com/better-auth/better-auth/pull/2107), but it hasn't been merged yet. **Workaround:** After generating your OpenAPI schema, patch the relevant response like this: ```js const schema = await auth.api.generateOpenAPISchema(); const signInEmailResp = schema.paths?.["/sign-in/email"]?.post?.responses?.["200"]?.content?.["application/json"]?.schema; if (signInEmailResp?.properties?.url) { signInEmailResp.properties.url.type = "string"; signInEmailResp.properties.url.nullable = true; } ``` If you encounter misplaced `required` arrays (inside `properties` instead of at the object level), move them up to be siblings of `properties`. Monitor [PR #2107](https://github.com/better-auth/better-auth/pull/2107) for a permanent fix. Until then, manual patching is the most reliable solution. <!-- 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/e92a9c32-3d5d-4425-a4a3-fe8b9b93fbb9?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/e92a9c32-3d5d-4425-a4a3-fe8b9b93fbb9?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/e92a9c32-3d5d-4425-a4a3-fe8b9b93fbb9?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/e92a9c32-3d5d-4425-a4a3-fe8b9b93fbb9?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/e92a9c32-3d5d-4425-a4a3-fe8b9b93fbb9?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/e92a9c32-3d5d-4425-a4a3-fe8b9b93fbb9?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/e92a9c32-3d5d-4425-a4a3-fe8b9b93fbb9?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=This%20is%20a%20known%20issue%3A%20the%20OpenAPI%20plugin%20in%20Better%20Auth%20generates%20an%20invalid%20schema%20for%20the%20%60/sign-in/email%60%20endpoint%2C%20specifically%20because%20the%20%60url%60%20property%20in%20the%20200%20response%20is%20defined%20as%20%60%22type%22%3A%20%22null%22%2C%20%22nullable%22%3A%20true%60%2C%20which%20is%20not%20allowed%20by%20OpenAPI%203.0/3.1%20and%20causes%20validation/codegen%20failures%20in%20tools%20like%20Orval.%20The%20actual%20implementation%20returns%20%60url%60%20as%20a%20string%20or%20undefined%2C%20so%20the%20schema%20should%20use%20%60%22type%22%3A%20%22string%22%2C%20%22nullable%22%3A%20true%22%60%20instead.%20There%20are%20also%20broader%20issues%20with%20misplaced%20%60required%60%20arrays%20and%20missing%20%60%24ref%60%20usage%20in%20some%20responses%2C%20which%20can%20break%20strict%20OpenAPI%20tooling.%20This%20bug%20is%20confirmed%20in%20v1.4.1%20and%20earlier%2C%20and%20is%20tracked%20in%20%5Bissue%20%232097%5D%28https%3A//github.com/better-auth/better-auth/issues/2097%29%20and%20%5Brelated%20discussions%5D%28https%3A//github.com/better-auth/better-auth/issues/5607%29.%0A%0AA%20permanent%20fix%20is%20pending%20in%20%5BPR%20%232107%5D%28https%3A//github.com/better-auth/better-auth/pull/2107%29%2C%20but%20it%20hasn%27t%20been%20merged%20yet.%0A%0A%2A%2AWorkaround%3A%2A%2A%20%20%0AAfter%20generating%20your%20OpenAPI%20schema%2C%20patch%20the%20relevant%20response%20like%20this%3A%0A%0A%60%60%60js%0Aconst%20schema%20%3D%20await%20auth.api.generateOpenAPISchema%28%29%3B%0Aconst%20signInEmailResp%20%3D%20schema.paths%3F.%5B%22/sign-in/email%22%5D%3F.post%3F.responses%3F.%5B%22200%22%5D%3F.content%3F.%5B%22application/json%22%5D%3F.schema%3B%0Aif%20%28signInEmailResp%3F.properties%3F.url%29%20%7B%0A%20%20signInEmailResp.properties.url.type%20%3D%20%22string%22%3B%0A%20%20signInEmailResp.properties.url.nullable%20%3D%20true%3B%0A%7D%0A%60%60%60%0AIf%20you%20encounter%20misplaced%20%60required%60%20arrays%20%28inside%20%60properties%60%20instead%20of%20at%20the%20object%20level%29%2C%20move%20them%20up%20to%20be%20siblings%20of%20%60properties%60.%0A%0AMonitor%20%5BPR%20%232107%5D%28https%3A//github.com/better-auth/better-auth/pull/2107%29%20for%20a%20permanent%20fix.%20Until%20then%2C%20manual%20patching%20is%20the%20most%20reliable%20solution.)&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/6250)
Author
Owner

@viniciuspatzer commented on GitHub (Nov 24, 2025):

Changing

"url": { "type": "null", "nullable": true }

To

"url": { "type": "string", "nullable": true }

This seems to have fixed the issue, but I'm not sure if this is the correct solution.

<!-- gh-comment-id:3568655703 --> @viniciuspatzer commented on GitHub (Nov 24, 2025): Changing ```json "url": { "type": "null", "nullable": true } ``` To ```json "url": { "type": "string", "nullable": true } ``` This seems to have fixed the issue, but I'm not sure if this is the correct solution.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#19089