generateOpenAPISchema emits $schema and $ref with sibling properties, breaking OpenAPI 3.0.x consumers #2882

Open
opened 2026-03-13 10:25:23 -05:00 by GiteaMirror · 0 comments
Owner

Originally created by @lipenvs on GitHub (Feb 17, 2026).

generateOpenAPISchema emits $schema and $ref with sibling properties, breaking OpenAPI 3.0.x consumers

Is this suited for github?

Yes

Description

When using auth.api.generateOpenAPISchema() and consuming the result in an OpenAPI 3.0.x context (e.g. @elysiajs/swagger), the generated schema contains two structural issues that cause runtime errors or silent data loss:

  1. $schema property — The generated schema includes a $schema meta-reference (e.g. "$schema": "https://json-schema.org/draft/2020-12/schema"). This is a JSON Schema 2020-12 construct and is not valid in OpenAPI 3.0.x, causing validation errors in consumers that strictly parse the spec.

  2. $ref with sibling properties — In OpenAPI 3.0.x, when a $ref is present in an object, all other sibling properties are ignored per spec. The schema generated by Better Auth sometimes includes extra properties alongside $ref, which causes fields (like required) to be silently dropped by 3.0.x consumers.

Note: this is related to but distinct from #6691, which addressed nullable: true vs type: ["string", "null"]. That fix was merged in #6705, but these two issues remain unaddressed as of v1.4.18.

To Reproduce

  1. Set up Better Auth with generateOpenAPISchema()
  2. Pass the result to an OpenAPI 3.0.x consumer (e.g. @elysiajs/swagger)
  3. Observe errors related to $schema being present, or fields going missing due to $ref with sibling properties

Current vs. Expected behavior

Current: The generated schema includes $schema and $ref objects with sibling properties, which are invalid or ignored in OpenAPI 3.0.x.

Expected: The schema should either be sanitized before output, or an option should be provided to generate a schema fully compliant with a specific OpenAPI version (3.0.x or 3.1.x).

Workaround

A recursive sanitization function can be applied over paths and components after calling generateOpenAPISchema():

function sanitizeForOpenAPI3(schema: unknown): unknown {
  if (Array.isArray(schema)) return schema.map(sanitizeForOpenAPI3)
  if (typeof schema !== 'object' || schema === null) return schema

  const record = schema as Record<string, unknown>

  // If $ref is present, strip all sibling properties
  if ('$ref' in record) return { $ref: record.$ref }

  const result: Record<string, unknown> = {}

  for (const [key, value] of Object.entries(record)) {
    // Remove $schema
    if (key === '$schema') continue

    // Convert type array to nullable (for OpenAPI 3.0.x consumers)
    if (key === 'type' && Array.isArray(value)) {
      const types = value.filter((t) => t !== 'null')
      result.type = types.length === 1 ? types[0] : types
      if (value.includes('null')) result.nullable = true
      continue
    }

    result[key] = sanitizeForOpenAPI3(value)
  }

  return result
}

What version of Better Auth are you using?

1.4.18

Which area(s) are affected?

Backend, OpenAPI plugin

  • #6691nullable: true vs OpenAPI 3.1 (partially related, fixed in #6705)
  • #6446id as not required in User/Session components (possibly a symptom of the $ref sibling issue)
Originally created by @lipenvs on GitHub (Feb 17, 2026). ## `generateOpenAPISchema` emits `$schema` and `$ref` with sibling properties, breaking OpenAPI 3.0.x consumers ### Is this suited for github? Yes ### Description When using `auth.api.generateOpenAPISchema()` and consuming the result in an OpenAPI 3.0.x context (e.g. `@elysiajs/swagger`), the generated schema contains two structural issues that cause runtime errors or silent data loss: 1. **`$schema` property** — The generated schema includes a `$schema` meta-reference (e.g. `"$schema": "https://json-schema.org/draft/2020-12/schema"`). This is a JSON Schema 2020-12 construct and is not valid in OpenAPI 3.0.x, causing validation errors in consumers that strictly parse the spec. 2. **`$ref` with sibling properties** — In OpenAPI 3.0.x, when a `$ref` is present in an object, all other sibling properties are ignored per spec. The schema generated by Better Auth sometimes includes extra properties alongside `$ref`, which causes fields (like `required`) to be silently dropped by 3.0.x consumers. Note: this is related to but distinct from #6691, which addressed `nullable: true` vs `type: ["string", "null"]`. That fix was merged in #6705, but these two issues remain unaddressed as of v1.4.18. ### To Reproduce 1. Set up Better Auth with `generateOpenAPISchema()` 2. Pass the result to an OpenAPI 3.0.x consumer (e.g. `@elysiajs/swagger`) 3. Observe errors related to `$schema` being present, or fields going missing due to `$ref` with sibling properties ### Current vs. Expected behavior **Current:** The generated schema includes `$schema` and `$ref` objects with sibling properties, which are invalid or ignored in OpenAPI 3.0.x. **Expected:** The schema should either be sanitized before output, or an option should be provided to generate a schema fully compliant with a specific OpenAPI version (3.0.x or 3.1.x). ### Workaround A recursive sanitization function can be applied over `paths` and `components` after calling `generateOpenAPISchema()`: ```ts function sanitizeForOpenAPI3(schema: unknown): unknown { if (Array.isArray(schema)) return schema.map(sanitizeForOpenAPI3) if (typeof schema !== 'object' || schema === null) return schema const record = schema as Record<string, unknown> // If $ref is present, strip all sibling properties if ('$ref' in record) return { $ref: record.$ref } const result: Record<string, unknown> = {} for (const [key, value] of Object.entries(record)) { // Remove $schema if (key === '$schema') continue // Convert type array to nullable (for OpenAPI 3.0.x consumers) if (key === 'type' && Array.isArray(value)) { const types = value.filter((t) => t !== 'null') result.type = types.length === 1 ? types[0] : types if (value.includes('null')) result.nullable = true continue } result[key] = sanitizeForOpenAPI3(value) } return result } ``` ### What version of Better Auth are you using? 1.4.18 ### Which area(s) are affected? Backend, OpenAPI plugin ### Related issues - #6691 — `nullable: true` vs OpenAPI 3.1 (partially related, fixed in #6705) - #6446 — `id` as not required in User/Session components (possibly a symptom of the `$ref` sibling issue)
GiteaMirror added the enhancementplugin labels 2026-03-13 10:25:24 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2882