Skip to content

fix(ai-openai): allow null for Batch.model, output_file_id, error_file_id#2146

Closed
lindit wants to merge 2 commits into
Effect-TS:mainfrom
lindit:fix/openai-batch-nullable-fields
Closed

fix(ai-openai): allow null for Batch.model, output_file_id, error_file_id#2146
lindit wants to merge 2 commits into
Effect-TS:mainfrom
lindit:fix/openai-batch-nullable-fields

Conversation

@lindit
Copy link
Copy Markdown

@lindit lindit commented May 9, 2026

Summary

Follow-up to #2145. Same class of bug, different schema: OpenAI returns null for several Batch fields that the OpenAPI spec marks as optional-only.

  • Batch.modelnull on freshly created batches that haven't been validated yet (observed downstream).
  • Batch.output_file_idnull until the batch completes successfully (likely; not yet observed in the wild but obvious candidate).
  • Batch.error_file_idnull unless errors occurred (likely; not yet observed but obvious candidate).

createBatch / retrieveBatch / listBatches fail decoding with:

SchemaError(Expected string, got null at ["model"])

This PR adds three JSON Patch entries to packages/ai/openai/codegen.yaml setting nullable: true on each (mirroring the precedent set by #2145 and the existing ModelResponseProperties.user/safety_identifier/prompt_cache_key patches). After regen, each field is emitted as:

"model": Schema.optionalKey(
  Schema.Union([Schema.String, Schema.Null]).annotate({ ... })
)

Note: stacked on #2145

This branch is built on top of fix/openai-files-status-details-null (#2145), so GitHub will show that PR's commit until #2145 merges to main. The Generated.ts diff unique to this PR is small and surgical (3 fields, 13 ins / 9 del):

-  readonly "model"?: string
+  readonly "model"?: string | null
...
-  readonly "output_file_id"?: string
-  readonly "error_file_id"?: string
+  readonly "output_file_id"?: string | null
+  readonly "error_file_id"?: string | null

Note: Batch.errors not patched (generator bug)

While sweeping, I noticed OpenAI's own example shows "errors": null (Batch component, line 40127 of the spec). I tried adding nullable: true for Batch.errors too, but the generator handles nullable: true on object-typed properties incorrectly — it produces a degenerate Schema.Union([Schema.Struct(...)]) with no Schema.Null member, and the corresponding TS type is unchanged. The string-typed fields in this PR work fine because the generator handles nullable: true on primitive-typed properties correctly.

I dropped that patch from the PR per the original guidance not to touch the generator. Worth filing as a separate generator bug; the workaround is to express it via anyOf: [{...object schema...}, {type: 'null'}] instead of nullable: true, which is significantly more verbose to encode as a JSON Patch.

Test plan

  • pnpm --filter @effect/ai-openai check passes
  • pnpm --filter @effect/ai-openai test passes (90 tests)
  • pnpm --filter @effect/ai-openai build passes
  • Manual verification: call createBatch against the live OpenAI API and confirm response decodes when model: null

🤖 Generated with Claude Code

lindit and others added 2 commits May 9, 2026 04:50
OpenAI returns `status_details: null` on /v1/files responses, but the
OpenAPI spec marks it optional-only, so createFile / retrieveFile /
listFiles failed decoding with `Expected string, got null at
["status_details"]`. Patched the codegen spec to mark the field nullable
and regenerated.

Note: the regen also picks up unrelated upstream OpenAPI spec drift
since the last regeneration on 2026-04-22.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…e_id

OpenAI returns `null` for these fields at various stages of the batch
lifecycle (model: null until validation, output_file_id: null until
completion, error_file_id: null unless errors occurred), but the OpenAPI
spec marks them optional-only. createBatch / retrieveBatch / listBatches
fail decoding with `Expected string, got null at [<field>]`. Patched the
codegen spec to mark all three nullable.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 9, 2026

🦋 Changeset detected

Latest commit: 68f6fd5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 27 packages
Name Type
@effect/ai-openai Patch
effect Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-node-shared Patch
@effect/platform-node Patch
@effect/vitest Patch
@effect/ai-anthropic Patch
@effect/ai-openai-compat Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/openapi-generator Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@lindit
Copy link
Copy Markdown
Author

lindit commented May 9, 2026

Closing — squashing into #2145.

@lindit lindit closed this May 9, 2026
@lindit lindit deleted the fix/openai-batch-nullable-fields branch May 9, 2026 03:29
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