Skip to content

fix(schema-to-json): support serializing Zod 4 z.date() to JSON Schema - #4962

Closed
kaiizer777 wants to merge 1 commit into
triggerdotdev:mainfrom
kaiizer777:fix/zod4-date-json-schema
Closed

kaiizer777 wants to merge 1 commit into
triggerdotdev:mainfrom
kaiizer777:fix/zod4-date-json-schema

Conversation

@kaiizer777

Copy link
Copy Markdown

Fixes #4939

Problem

In @trigger.dev/schema-to-json, converting a Zod 4 schema that includes z.date() threw an uncaught error:

Date cannot be represented in JSON Schema

This crashed MCP tools/list responses as well as schema generation/indexing when task payloads or tools utilized z.date().

Root Cause

convertZod4Schema in packages/schema-to-json/src/index.ts called z4.toJSONSchema(schema, ...) without configuring an unrepresentable handler. In Zod 4, dateProcessor invokes handleUnrepresentable, which defaults to "throw".

Solution

  1. Configured unrepresentable in z4.toJSONSchema to map date nodes to { type: "string", format: "date-time" }, achieving parity with Zod 3 (zod-to-json-schema).
  2. Maintained strict "throw" behavior for other unrepresentable types (e.g. undefined, symbol).
  3. Added date formatting in override to ensure schema consistency.
  4. Added unit tests for z.date() standalone and nested in objects with optional/nullable/array wrappers across both Zod 4 and minimum Zod 3 permalink.
  5. Added user-facing patch changeset for @trigger.dev/schema-to-json.

Verification

  • pnpm --filter "@trigger.dev/schema-to-json" run test -- --run (25 passed)
  • pnpm --filter trigger.dev run test src/mcp/schemas.test.ts -- --run (20 passed)
  • pnpm run build --filter "@trigger.dev/schema-to-json"
  • pnpm exec oxfmt packages/schema-to-json/src/index.ts packages/schema-to-json/tests/index.test.ts
  • pnpm exec oxlint packages/schema-to-json/src/index.ts packages/schema-to-json/tests/index.test.ts

triggerdotdev#4939)

In Zod 4, toJSONSchema delegates Date schemas to handleUnrepresentable, which threw 'Date cannot be represented in JSON Schema' when unrepresentable was omitted. Configure unrepresentable to return { type: 'string', format: 'date-time' } for date schemas to match Zod 3 output while preserving strict error handling for other unrepresentable types.
@changeset-bot

changeset-bot Bot commented Sep 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ccad17a

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

This PR includes changesets to release 27 packages
Name Type
@trigger.dev/schema-to-json Patch
trigger.dev Patch
@internal/dashboard-agent Patch
@trigger.dev/build Patch
@trigger.dev/core Patch
@trigger.dev/python Patch
@trigger.dev/react-hooks Patch
@trigger.dev/redis-worker Patch
@trigger.dev/rsc Patch
@trigger.dev/sdk Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer Patch
@trigger.dev/rbac Patch
@trigger.dev/sso Patch
@internal/clickhouse Patch
@internal/llm-model-catalog Patch
@internal/metrics-pipeline Patch
@internal/redis Patch
@internal/replication Patch
@internal/run-engine Patch
@internal/run-store Patch
@internal/schedule-engine Patch
@internal/tracing Patch
@internal/webhook-engine Patch
@internal/webhook-sources Patch
@internal/testcontainers Patch
@internal/cache 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

@github-actions

Copy link
Copy Markdown
Contributor

Hi @kaiizer777, thanks for your interest in contributing!

This project requires that pull request authors are vouched, and you are not in the list of vouched users.

This PR will be closed automatically. See https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md for more details.

@github-actions github-actions Bot closed this Sep 20, 2026
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: caf9e6ac-8c57-4fc7-9dfc-45baa025119f

📥 Commits

Reviewing files that changed from the base of the PR and between 414e5a2 and ccad17a.

📒 Files selected for processing (3)
  • .changeset/fix-zod4-date-json-schema.md
  • packages/schema-to-json/src/index.ts
  • packages/schema-to-json/tests/index.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@devin-ai-integration devin-ai-integration Bot 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.

Devin Review found 1 potential issue.

Devin Review

Comment on lines +159 to +165
unrepresentable: ({ zodSchema }) => {
const def = (zodSchema as any)._zod?.def;
if (def?.type === "date") {
return { type: "string", format: "date-time" };
}
return "throw";
},

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.

🟡 Older Zod versions weaken schemas

With Zod 4.0–4.4, the unrepresentable function disables throwing for non-date types. Those releases only compare the option with "throw", so unsupported schemas become {} and accept rejected values.

Learn more

The package accepts Zod ^4.0.0, but function-valued unrepresentable handlers were added only in later Zod 4 releases. Earlier releases treat every value except the literal "throw" as permissive behavior. The callback therefore never runs there, although the existing override still converts dates. Other unrepresentable nodes lose their previous errors and emit unconstrained schemas.

Example: With Zod 4.1, converting z.symbol() previously throws. After this change it emits {}, which permits strings and numbers even though z.symbol() rejects them.

Recommended fix: Either raise both Zod dependency ranges to the first version supporting UnrepresentableHandler, or preserve compatibility by detecting that capability and explicitly throwing from override for every non-date unrepresentable node on older releases. Add a test installed against the minimum supported Zod 4 version.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

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.

MCP tools/list fails with "Date cannot be represented in JSON Schema" when a tool schema uses z.date() (Zod 4)

1 participant