Skip to content

fix(ai): add nullable() to configFiles schema to support OpenAI stric…#4268

Open
qveys wants to merge 1 commit intoDokploy:canaryfrom
qveys:patch-1
Open

fix(ai): add nullable() to configFiles schema to support OpenAI stric…#4268
qveys wants to merge 1 commit intoDokploy:canaryfrom
qveys:patch-1

Conversation

@qveys
Copy link
Copy Markdown

@qveys qveys commented Apr 21, 2026

…t mode

OpenAI strict mode requires all keys in properties to also appear in required. The configFiles field was marked as .optional() in the Zod schema, which generates a JSON Schema where configFiles is in properties but not in required, causing the error:

"Invalid schema for response_format 'response': In context=('properties', 'suggestions', 'items'), 'required' is required to be supplied and to be an array including every key in properties. Missing 'configFiles'."

Adding .nullable() before .optional() generates an anyOf: [{...}, {type: 'null'}] pattern while keeping configFiles in required, which is compatible with OpenAI strict mode.

Fixes #4267

What is this PR about?

Please describe in a short paragraph what this PR is about.

Checklist

Before submitting this PR, please make sure that:

  • You created a dedicated branch based on the canary branch.
  • You have read the suggestions in the CONTRIBUTING.md file https://github.com/Dokploy/dokploy/blob/canary/CONTRIBUTING.md#pull-request
  • You have tested this PR in your local instance. If you have not tested it yet, please do so before submitting. This helps avoid wasting maintainers' time reviewing code that has not been verified by you.

Issues related (if applicable)

closes #123

Screenshots (if applicable)

Greptile Summary

This PR fixes an OpenAI strict-mode schema incompatibility by adding .nullable() before .optional() on the configFiles Zod field. When using the Vercel AI SDK's OpenAI provider, zod-to-json-schema transforms .nullable().optional() fields into required-but-nullable properties (adding them to required with an anyOf: [{…}, {type: "null"}] type), satisfying the constraint that every key in properties must appear in required.

Confidence Score: 5/5

Safe to merge — the change is a one-line fix with no runtime risk and all consumers already guard against falsy values.

The fix is correct and well-targeted. All callers use truthy checks or optional chaining, so a null value returned by the model is handled safely. The only remaining note is a minor TypeScript type inconsistency in the DockerOutput interface that has no production impact.

No files require special attention.

Comments Outside Diff (1)

  1. packages/server/src/services/ai.ts, line 27 (link)

    P2 DockerOutput interface not updated for null

    The configFiles field in DockerOutput is typed as Array<...> | undefined (via ?:), but the Zod schema now also allows null. At runtime the AI model could return null for this field, which would be mis-typed. All current consumers use truthy/optional-chaining guards so there is no runtime breakage, but a strict TypeScript assignment (const f: typeof item.configFiles = item.configFiles) could silently accept a null value. Keeping the interface in sync avoids confusion.

Reviews (1): Last reviewed commit: "fix(ai): add nullable() to configFiles s..." | Re-trigger Greptile

…t mode

OpenAI strict mode requires all keys in `properties` to also appear in `required`. The `configFiles` field was marked as `.optional()` in the Zod schema, which generates a JSON Schema where `configFiles` is in `properties` but not in `required`, causing the error:

"Invalid schema for response_format 'response': In context=('properties', 'suggestions', 'items'), 'required' is required to be supplied and to be an array including every key in properties. Missing 'configFiles'."

Adding `.nullable()` before `.optional()` generates an `anyOf: [{...}, {type: 'null'}]` pattern while keeping `configFiles` in `required`, which is compatible with OpenAI strict mode.

Fixes Dokploy#4267
@qveys qveys requested a review from Siumauricio as a code owner April 21, 2026 02:54
Copilot AI review requested due to automatic review settings April 21, 2026 02:54
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Apr 21, 2026
@dosubot dosubot Bot added the bug Something isn't working label Apr 21, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to fix the AI Assistant’s OpenAI strict-mode response_format schema validation error by adjusting how the configFiles field is represented in the Zod schema used for structured variant suggestions.

Changes:

  • Updates the Zod schema for configFiles under suggestVariants to include nullable() in addition to optional().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 132 to +139
configFiles: z
.array(
z.object({
content: z.string(),
filePath: z.string(),
}),
)
.optional(),
.nullable().optional(),
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

configFiles is still wrapped in .optional() here, so the generated JSON Schema will likely continue omitting it from the object's required array—this seems to leave the OpenAI strict-mode error unresolved. To satisfy strict mode, configFiles should be a required property and represent “no files” via an empty array (preferred, to avoid null leaking downstream) or via nullable without optional (and then ensure downstream types/validators accept null).

Copilot uses AI. Check for mistakes.
}),
)
.optional(),
.nullable().optional(),
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

This change is targeting OpenAI strict-mode JSON Schema generation; it would be safer to add a regression test that asserts the produced schema includes configFiles in the required array (and that its type matches the intended “optional” representation, e.g. empty array or nullable). The repo already has Vitest coverage for other server-exported utilities, so a small unit test would help prevent future SDK/schema changes from reintroducing this failure.

Suggested change
.nullable().optional(),
.nullable(),

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] AI Assistant fails with "Invalid schema for response_format": Missing 'configFiles' in required array

2 participants