Skip to content

fix(zod): omit impossible optional branch in strict schemas - #2751

Merged
HAYDEN-OAI merged 1 commit into
mainfrom
codex/zod-shared-optional-minimal
Sep 16, 2026
Merged

HAYDEN-OAI merged 1 commit into
mainfrom
codex/zod-shared-optional-minimal

Conversation

@HAYDEN-OAI

Copy link
Copy Markdown
Contributor
  • I understand that this repository is auto-generated and my pull request may not be merged

Changes being requested

Shared Zod v3 .nullable().optional() fields can generate extracted definitions containing anyOf: [{ not: {} }, innerSchema]. The not branch accepts no JSON values and is unsupported by strict Structured Outputs.

For strict conversion without an override callback, generate anyOf: [innerSchema] and parse the child at anyOf/0. Keeping the wrapper preserves existing optional-root diagnostics and metadata behavior, while generating references against the final layout avoids post-processing or reference repair. Non-strict and override-enabled conversion retain their existing behavior.

The production change is six added lines and seven removed lines in the optional parser. Focused tests cover all four strict helpers, both nullable/optional orders, supplied definitions and descriptions, escaped definition names, shared nested and recursive schemas, and non-strict/override controls.

Additional context & links

Fixes #2462. Supersedes #2463 with a smaller fix at schema generation. The acceptance scope is removing the generated impossible optional branch while preserving valid references and existing diagnostics; general JSON Schema normalization is outside this change.

Validation:

  • New regression suite: 17 passed; 16 fail against the unchanged parser and the non-strict/override control passes.
  • Schema/helper suite: 1,154 passed.
  • Full handwritten unit suite: 8,677 passed, four failures in tests/node-version-review.test.ts. The same four failures reproduce with the parser change removed.
  • ./scripts/lint, pnpm exec tsc --noEmit, and pnpm build passed using Node 24.19.0.
  • Built CommonJS and ESM helper regressions passed on Node 22.0.0 and Node 24.19.0.
  • Independent review found no correctness or security findings. No live API request was used for validation.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-16T15:45:44.624073Z 07dd324 PR opened
🔒 Security Review ✅ Completed 2026-09-16T15:46:27.865290Z 07dd324 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Co-authored-by: cmun2 <dkdkdkalalal@naver.com>
@HAYDEN-OAI
HAYDEN-OAI force-pushed the codex/zod-shared-optional-minimal branch from 07dd324 to 3a14cd4 Compare September 16, 2026 15:44
@github-actions

Copy link
Copy Markdown
Contributor

Castiron custom code

✅ No new custom-code files detected.

45 mixed files remain; 0 existing customizations changed.

Compared 425502d2bf2d → 3a14cd427d6f. Generated baselines verified.

45 existing customizations unchanged
  • api.md
  • scripts/castiron/README.md
  • scripts/castiron/custom_code_report.py
  • scripts/castiron/test_custom_code_report.py
  • src/client.ts
  • src/resources/audio/transcriptions.ts
  • src/resources/audio/translations.ts
  • src/resources/beta/agents/environments/files.ts
  • src/resources/beta/agents/sessions/sessions.ts
  • src/resources/beta/assistants.ts
  • src/resources/beta/beta.ts
  • src/resources/beta/index.ts
  • src/resources/beta/responses/internal-base.ts
  • src/resources/beta/responses/responses.ts
  • src/resources/beta/responses/ws-base.ts
  • src/resources/beta/responses/ws.ts
  • src/resources/beta/threads/index.ts
  • src/resources/beta/threads/runs/index.ts
  • src/resources/beta/threads/runs/runs.ts
  • src/resources/beta/threads/threads.ts
  • src/resources/chat/completions/completions.ts
  • src/resources/chat/completions/index.ts
  • src/resources/conversations/index.ts
  • src/resources/embeddings.ts
  • src/resources/files.ts
  • src/resources/fine-tuning/checkpoints/permissions.ts
  • src/resources/images.ts
  • src/resources/live/forks/ws-base.ts
  • src/resources/live/forks/ws.ts
  • src/resources/live/sideband/ws-base.ts
  • src/resources/live/sideband/ws.ts
  • src/resources/live/ws-base.ts
  • src/resources/live/ws.ts
  • src/resources/responses/internal-base.ts
  • src/resources/responses/responses.ts
  • src/resources/responses/ws-base.ts
  • src/resources/responses/ws.ts
  • src/resources/skills/skills.ts
  • src/resources/skills/versions/versions.ts
  • src/resources/vector-stores/file-batches.ts

5 more in the full report.

A changed generated baseline means this report cannot reliably identify which handwritten lines changed.

Inspect the custom-code diff

Download the exact patch produced by this run (requires repository access):

gh run download 35117398579 --repo openai/openai-node \
  --name castiron-custom-code-35117398579-1 --dir /tmp/castiron-custom-code-35117398579-1
git apply --stat /tmp/castiron-custom-code-35117398579-1/custom-code.patch
cat /tmp/castiron-custom-code-35117398579-1/custom-code.patch

Or reproduce it from an SDK checkout containing the vendored reporter:

git fetch --no-tags origin 425502d2bf2da1bdd37efda3b0fa5add96fc8a51 3a14cd427d6f16545c8d2eb48d3a7098a92f0b3b
python3 scripts/castiron/custom_code_report.py report \
  --base 425502d2bf2da1bdd37efda3b0fa5add96fc8a51 \
  --head 3a14cd427d6f16545c8d2eb48d3a7098a92f0b3b --fetch --require-head-hash --public \
  --out /tmp/castiron-custom-code-3a14cd427d6f
cat /tmp/castiron-custom-code-3a14cd427d6f/custom-code.patch

This is the current full custom patch for mixed files, not an attribution of only the handwritten lines changed by this PR.

Full report and patch

@openai-sdks

openai-sdks Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

OkTest Summary

✅ 236/236 SDK tests passed in 9.584s for Node SDK PR #2751.

Test results — 42 files
Test Result Time
tests/chat-completions-complex-body.test.ts ✅ Passed 111ms
tests/chat-completions-create.test.ts ✅ Passed 197ms
tests/chat-completions-stream.test.ts ✅ Passed 113ms
tests/files-content-binary.test.ts ✅ Passed 453ms
tests/files-create-multipart.test.ts ✅ Passed 320ms
tests/files-list-pagination.test.ts ✅ Passed 291ms
tests/initialize-config.test.ts ✅ Passed 105ms
tests/instance-isolation.test.ts ✅ Passed 78ms
tests/models-list.test.ts ✅ Passed 191ms
tests/responses-background-lifecycle.test.ts ✅ Passed 131ms
tests/responses-body-method-errors.test.ts ✅ Passed 226ms
tests/responses-cancel-timeout.test.ts ✅ Passed 184ms
tests/responses-cancel.test.ts ✅ Passed 199ms
tests/responses-compact-retries.test.ts ✅ Passed 191ms
tests/responses-compact.test.ts ✅ Passed 170ms
tests/responses-create-advanced-stream.test.ts ✅ Passed 96ms
tests/responses-create-advanced.test.ts ✅ Passed 150ms
tests/responses-create-disconnect.test.ts ✅ Passed 1.076s
tests/responses-create-errors.test.ts ✅ Passed 278ms
tests/responses-create-malformed-api-responses.test.ts ✅ Passed 187ms
tests/responses-create-retries.test.ts ✅ Passed 342ms
tests/responses-create-stream-failures.test.ts ✅ Passed 112ms
tests/responses-create-stream-timeout.test.ts ✅ Passed 2.13s
tests/responses-create-stream-wire.test.ts ✅ Passed 1.894s
tests/responses-create-stream.test.ts ✅ Passed 78ms
tests/responses-create-terminal-states.test.ts ✅ Passed 158ms
tests/responses-create-timeout.test.ts ✅ Passed 181ms
tests/responses-create.test.ts ✅ Passed 207ms
tests/responses-delete.test.ts ✅ Passed 208ms
tests/responses-input-items-errors.test.ts ✅ Passed 127ms
tests/responses-input-items-list.test.ts ✅ Passed 151ms
tests/responses-input-items-options.test.ts ✅ Passed 165ms
tests/responses-input-tokens-count-timeout.test.ts ✅ Passed 215ms
tests/responses-input-tokens-count.test.ts ✅ Passed 273ms
tests/responses-malformed-inputs.test.ts ✅ Passed 1.533s
tests/responses-not-found-errors.test.ts ✅ Passed 150ms
tests/responses-parse.test.ts ✅ Passed 129ms
tests/responses-retrieve-retries.test.ts ✅ Passed 217ms
tests/responses-retrieve.test.ts ✅ Passed 203ms
tests/responses-stored-method-errors.test.ts ✅ Passed 689ms
tests/retry-behavior.test.ts ✅ Passed 3.065s
tests/sdk-error-shape.test.ts ✅ Passed 392ms

View OkTest run #35117356433

SDK merge (157657f378e9) · head (3a14cd427d6f) · base (425502d2bf2d) · OkTest (c6ef21c7db64)

@markstuart-oai markstuart-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed 3a14cd427d6f16545c8d2eb48d3a7098a92f0b3b. This is a good simplification at the owning boundary: omit the impossible optional branch during generation and register the child at its final anyOf/0 path. Keeping the wrapper preserves annotations and optional-root diagnostics, while the explicit override guard retains existing callback output and path behavior.

No actionable findings after independent reference and compatibility reviews. Shared, nested, recursive, and supplied-definition cases preserve reference meaning; non-strict conversion, custom overrides, Zod v4, Realtime, and response parsing retain their existing contracts.

Validation: 1,127 schema/helper tests passed, including all 17 new regressions; lint, typecheck, and build passed. Built CJS and ESM helpers passed conversion, reference, parsing, and root-diagnostic probes on Node 22.0.0 and 24.20.0. CI for this commit passed, including the Node 22/24/26 matrix. All validation was local or CI; no live API calls were made.

@jbeckwith-oai jbeckwith-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed exact head 3a14cd427d6f16545c8d2eb48d3a7098a92f0b3b; no blocking findings. The change removes only the impossible strict-mode optional branch and records the child at its final anyOf/0 path, while preserving the wrapper, non-strict generation, and caller override behavior. Shared, nested, recursive, and supplied-definition references remain valid. I ran the 17 focused regressions and the full Zod helper suite locally (811 tests); all passed. Current CI, CodeQL, Castiron, and OkTest (236/236) are green.

@HAYDEN-OAI
HAYDEN-OAI added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit 2b4c2c7 Sep 16, 2026
38 checks passed
@HAYDEN-OAI
HAYDEN-OAI deleted the codex/zod-shared-optional-minimal branch September 16, 2026 16:01
@openai-sdks openai-sdks Bot mentioned this pull request Sep 16, 2026
HAYDEN-OAI pushed a commit that referenced this pull request Sep 16, 2026
Automated Release PR
---


##
[7.17.0](v7.16.0...v7.17.0)
(2026-09-16)


### Features

* **api:** add compaction progress events
([#2749](#2749))
([425502d](425502d))


### Bug Fixes

* **ci:** retry transient Deno download failures
([#2752](#2752))
([e39037b](e39037b))
* preserve chat runner abort reasons
([#2607](#2607))
([eda4d0c](eda4d0c))
* **realtime:** preserve native WebSocket error causes
([#2715](#2715))
([58fa72a](58fa72a))
* **responses:** reject function-based API keys in WebSocket
constructors
([#2586](#2586))
([eea7618](eea7618))
* **runners:** reject unfinished turns in streaming runTools
([#2716](#2716))
([937ed67](937ed67))
* **streaming:** emit terminal SSE events missing a trailing blank line
([#2726](#2726))
([94d6418](94d6418))
* **zod:** omit impossible optional branch in strict schemas
([#2751](#2751))
([2b4c2c7](2b4c2c7))


### Chores

* update lint tooling and tailor anti-slop for the SDK
([#2753](#2753))
([21a03c2](21a03c2))


### Documentation

* **examples:** preserve split UTF-8 in raw stream consumer
([#2714](#2714))
([f44152a](f44152a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
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 v3: a .nullable().optional() schema shared by two fields is encoded two different ways, and one of them uses not

3 participants