Skip to content

zodTextFormat generates invalid circular $ref in JSON schema definitions #1739

@dario-causaly

Description

@dario-causaly

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

When using zodTextFormat to convert a Zod schema, the generated JSON schema contains a $ref that references itself, creating an invalid circular definition that cannot be resolved.

To Reproduce

  1. Create a Zod schema as shown in the code snippet.
  2. Pass it to zodTextFormat(schema, "slidePlan").
  3. Inspect the generated definitions block in the output.

Notes:

  1. Only occurs for zod/v3
  2. Seems to be related to the brand applied to BlockIdSchema
  3. If the result is used for text.format of a responses.parse() call, a rather cryptic error is shown:
SyntaxError: Unexpected end of JSON input 
    at JSON.parse (<anonymous>)

Code snippets

import { zodTextFormat } from "openai/helpers/zod";

import { z } from "zod/v3";

const BlockIdSchema = z.string().brand<"SlideId">();

const SlidePlanSchema = z.object({
  slides: z.array(
    z.object({
      subtitle: z.array(BlockIdSchema).nullable(),
      content: z.array(BlockIdSchema).min(1),
    }),
  ),
});

const jsonSchema = zodTextFormat(SlidePlanSchema, "slidePlan");
console.dir(jsonSchema, { depth: null });

This outputs:

{
  type: 'json_schema',
  name: 'slidePlan',
  strict: true,
  schema: {
    type: 'object',
    properties: {
      slides: {
        type: 'array',
        items: {
          type: 'object',
          properties: {
            subtitle: {
              anyOf: [
                { type: 'array', items: { type: 'string' } },
                { type: 'null' }
              ]
            },
            content: {
              type: 'array',
              items: {
                '$ref': '#/definitions/slidePlan_properties_slides_items_properties_subtitle_anyOf_0_items'
              },
              minItems: 1
            }
          },
          required: [ 'subtitle', 'content' ],
          additionalProperties: false
        }
      }
    },
    required: [ 'slides' ],
    additionalProperties: false,
    definitions: {
      slidePlan_properties_slides_items_properties_subtitle_anyOf_0_items: {
        '$ref': '#/definitions/slidePlan_properties_slides_items_properties_subtitle_anyOf_0_items'
      },
      slidePlan: {
        type: 'object',
        properties: {
          slides: {
            type: 'array',
            items: {
              type: 'object',
              properties: {
                subtitle: {
                  anyOf: [
                    { type: 'array', items: { type: 'string' } },
                    { type: 'null' }
                  ]
                },
                content: {
                  type: 'array',
                  items: {
                    '$ref': '#/definitions/slidePlan_properties_slides_items_properties_subtitle_anyOf_0_items'
                  },
                  minItems: 1
                }
              },
              required: [ 'subtitle', 'content' ],
              additionalProperties: false
            }
          }
        },
        required: [ 'slides' ],
        additionalProperties: false
      }
    },
    '$schema': 'http://json-schema.org/draft-07/schema#'
  }
}

Under definitions, there is a circular reference:

    definitions: {
      slidePlan_properties_slides_items_properties_subtitle_anyOf_0_items: {
        '$ref': '#/definitions/slidePlan_properties_slides_items_properties_subtitle_anyOf_0_items'
      },
    ...

OS

Ubuntu

Node version

v24.13.0

Library version

openai v6.17.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions