Skip to content

Fix Zod v4 oneOf unions in strict schemas#1896

Open
kiwigitops wants to merge 2 commits into
openai:masterfrom
kiwigitops:fix-zod-oneof-strict-schema
Open

Fix Zod v4 oneOf unions in strict schemas#1896
kiwigitops wants to merge 2 commits into
openai:masterfrom
kiwigitops:fix-zod-oneof-strict-schema

Conversation

@kiwigitops
Copy link
Copy Markdown

Closes #1709

Zod v4 can emit oneOf for discriminated unions, but strict OpenAI schemas support anyOf instead. This converts oneOf unions before the existing strict-schema recursion runs, so nested discriminated unions are still processed normally.

Verification:

  • yarn jest tests/helpers/zod.test.ts --runInBand
  • yarn jest tests/lib/transform.test.ts tests/helpers/zod.test.ts --runInBand
  • git diff --check

@kiwigitops kiwigitops requested a review from a team as a code owner May 23, 2026 05:51
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6713349141

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/lib/transform.ts Outdated
// Handle unions (OpenAI strict mode supports anyOf, but not oneOf)
const oneOf = jsonSchema.oneOf;
if (Array.isArray(oneOf)) {
jsonSchema.anyOf = Array.isArray(jsonSchema.anyOf) ? [...jsonSchema.anyOf, ...oneOf] : oneOf;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve oneOf semantics when anyOf already exists

When a schema contains both anyOf and oneOf, this change concatenates the oneOf variants into anyOf, which weakens validation semantics from “must satisfy both keywords” to a single OR over all variants. In JSON Schema, anyOf and oneOf are independent constraints, so merging them can make previously invalid data pass validation. This can silently broaden accepted outputs for mixed-composition schemas rather than only translating unsupported oneOf usage.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Addressed in 2957e7f. The oneOf rewrite now preserves mixed-composition semantics instead of flattening into an existing anyOf: standalone oneOf becomes an allOf of anyOf plus a not(any overlap) exclusivity guard, and when a schema already has anyOf we keep that as a separate allOf term rather than merging the variants. Added regression coverage for mixed anyOf/oneOf schemas, and yarn jest tests/helpers/zod.test.ts --runInBand plus yarn jest tests/lib/transform.test.ts tests/helpers/zod.test.ts --runInBand pass.

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.

Zod schema conversion broken for unions in Zod 4.1.13+

2 participants