Skip to content

fix(downgrader): stop emitting nullable without type in 3.1 to 3.0 - #20

Merged
dinwwwh merged 1 commit into
mainfrom
claude/null-only-schemas-nullable-51243b
Sep 26, 2026
Merged

dinwwwh merged 1 commit into
mainfrom
claude/null-only-schemas-nullable-51243b

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Sep 26, 2026

Copy link
Copy Markdown
Member

The 3.1 → 3.0 downgrader no longer puts nullable: true on schemas that have no type. Null-only schemas now come out as { enum: [null] }. As a result, the Pydantic/FastAPI pattern anyOf: [X, { type: 'null' }] produces schemas that Ajv 8 can compile.

Fixes

  • type: 'null' and const: null no longer produce nullable without type. OpenAPI 3.0 ignores that combination, and Ajv 8 refuses to compile it ("nullable" cannot be used without "type").
  • const: null alongside several types no longer adds nullable at the top level, where there is no type, so these schemas compile too.
  • { const: null, type: 'string' } now accepts no value, like the source schema. Before, it accepted null.

Schemas whose type lists null alongside another type are unchanged: they still get type plus nullable: true.

Testing

  • Every converted case compiles in Ajv 8 and accepts the same values as the 3.1 source.
  • Updated the null-only and const: null expectations, and added cases for the anyOf pattern, a multi-type null const, and a null const with a non-null type.
  • The README's schema mapping table is updated to match.

Null-only schemas and null consts were converted with nullable: true but
no type. OpenAPI 3.0 ignores nullable without type, and Ajv 8 refuses to
compile such schemas, which broke the common anyOf: [X, {type: 'null'}]
pattern. Emit a plain null enum instead.
@codecov

codecov Bot commented Sep 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Null-only schemas no longer emit nullable without type — the rest.length === 0 branch in applyTypes drops out.nullable = true, so { type: 'null' } now converts to { enum: [null] } instead of the Ajv-invalid { enum: [null], nullable: true }.
  • const: null no longer forces nullable — convertConst is reduced to emitting the single-value enum, which also fixes { const: null, type: 'string' }: it previously accepted null and now correctly accepts nothing.
  • Tests and README — updated the null-only and const: null expectations, added the anyOf: [X, { type: 'null' }] FastAPI pattern, the multi-type null const, and the contradicting-type cases; synced the mapping table.

I independently reproduced the Ajv 8.20.0 behaviour against the pnpm-store copy: { nullable: true } fails to compile with "nullable" cannot be used without "type", while { enum: [null] }, { type: 'string', enum: [null] }, and anyOf: [{ type: 'string' }, { enum: [null] }] all compile and accept exactly the values the 3.1 sources do. pnpm test (353 passing), pnpm lint, and pnpm type:check are all green.

One non-blocking note: the repo has no Ajv dependency, so the semantic-equivalence checks described in the PR body are not captured by the in-repo suite (@seriousme/openapi-schema-validator only validates structure). The specific regression is still pinned by the toEqual expectations, so nothing needs to change here.

Pullfrog  | View workflow run | Using DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

@dinwwwh
dinwwwh merged commit a34a9b9 into main Sep 26, 2026
7 checks passed
@dinwwwh
dinwwwh deleted the claude/null-only-schemas-nullable-51243b branch September 27, 2026 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant