Skip to content

Zod schema conversion broken for unions in Zod 4.1.13+ #1709

@jfancher

Description

@jfancher

Confirm this is a Node library issue and not an underlying OpenAI API issue

  • This is an issue with the Node library

Describe the bug

Zod recently started emitting oneOf instead of anyOf for discriminated unions:
colinhacks/zod#5453

This is not supported for OpenAI strict mode, so using the Zod conversion helpers will cause API failures upon upgrading to the latest Zod.

To Reproduce

  • Define a discriminated union with Zod v4.1.13
  • Use one of the openai/helpers/zod functions
  • Use the result with the appropriate OpenAI endpoint
  • It fails because the JSON schema includes oneOf, which is unsupported by OpenAI

Code snippets

import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";
import { OpenAI } from "openai";

const ResponseSchema = z.object({
  data: z.discriminatedUnion("type", [
    z.object({ type: z.literal("a") }),
    z.object({ type: z.literal("b") }),
  ]),
});

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY
});

const completion = await client.chat.completions.parse({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Choose a or b"}],
  response_format: zodResponseFormat(ResponseSchema, "choice"),
});

// Result:
// {
//   status: 400,
//   headers: Headers {},
//   requestID: 'req_a7f2a1dc6e19439289ff6992bec4a24d',
//   error: {
//     message: "Invalid schema for response_format 'choice': In context=('properties', 'data'), 'oneOf' is not permitted.",
//     type: 'invalid_request_error',
//     param: 'response_format',
//     code: null
//   },
//   code: null,
//   param: 'response_format',
//   type: 'invalid_request_error'
// }

OS

N/A

Node version

N/A

Library version

openai v6.9.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsdk

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions