Skip to content

fix: sanitize ~standard property from Zod v4 JSON schemas#134

Merged
mattapperson merged 5 commits intomainfrom
fix/zod-v4-standard-schema-sanitization
Jan 7, 2026
Merged

fix: sanitize ~standard property from Zod v4 JSON schemas#134
mattapperson merged 5 commits intomainfrom
fix/zod-v4-standard-schema-sanitization

Conversation

@mattapperson
Copy link
Copy Markdown
Collaborator

Summary

  • Add sanitizeJsonSchema() function that recursively removes any keys prefixed with ~ from JSON schema objects
  • Update convertZodToJsonSchema() to sanitize schemas before returning
  • Add comprehensive unit tests for the sanitization function
  • Add integration test verifying no ~ prefixed keys exist in converted schemas

Problem

Zod v4's toJSONSchema() method includes a hidden ~standard property (from the Standard Schema specification) that:

  • Is enumerable via Object.keys() but doesn't appear in JSON.stringify() output
  • Gets included when the SDK serializes requests to downstream providers
  • Causes 400 errors from providers like Anthropic that reject unknown schema properties

Solution

Sanitize JSON schemas by removing any keys prefixed with ~ before sending requests to downstream providers.

Fixes #131

Test plan

  • Unit tests for sanitizeJsonSchema() cover edge cases (root level, nested objects, arrays, primitives)
  • Integration test verifies convertZodToJsonSchema() produces clean schemas
  • All existing tests pass
  • TypeScript types check
  • ESLint passes

Zod v4's toJSONSchema() includes a ~standard property from the Standard
Schema specification that causes 400 errors with downstream providers
like Anthropic.

Add sanitizeJsonSchema() function that recursively removes any keys
prefixed with ~ from JSON schema objects before sending to the API.

Fixes #131
Copy link
Copy Markdown

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 fixes an issue where Zod v4's toJSONSchema() method includes a ~standard property that causes 400 errors from downstream providers like Anthropic. The solution sanitizes JSON schemas by recursively removing all keys prefixed with ~ before sending requests.

Key Changes:

  • Added sanitizeJsonSchema() function that recursively removes ~ prefixed properties from objects and arrays
  • Updated convertZodToJsonSchema() to apply sanitization before returning schemas
  • Added comprehensive unit and integration tests to verify the sanitization works correctly

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/lib/tool-executor.ts Implements sanitizeJsonSchema() function and integrates it into convertZodToJsonSchema() to remove metadata properties before sending to providers
tests/unit/schema-sanitization.test.ts Adds unit tests covering edge cases for the sanitization function including nested objects, arrays, primitives, and the integration test for convertZodToJsonSchema()
tests/e2e/callModel-tools.test.ts Adds integration test verifying that converted Zod schemas don't contain any ~ prefixed keys in the "Zod Schema Conversion" test suite

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

Comment thread tests/unit/schema-sanitization.test.ts Outdated
@mattapperson mattapperson force-pushed the fix/zod-v4-standard-schema-sanitization branch from 250ad6c to cb0ea8e Compare January 7, 2026 16:32
Move duplicated helper function to tests/utils/schema-test-helpers.ts
for consistency across unit and e2e tests.
The test for tool.preliminary_result events involves making an API call,
waiting for the model to invoke the tool, executing the generator, and
streaming results back. CI environments are slower than local development,
so increased the timeout from 45s to 90s to prevent flaky failures.
Switch from openai/gpt-4o-mini to anthropic/claude-haiku-4.5 for more
reliable tool calling behavior in CI.
@seawatts
Copy link
Copy Markdown

seawatts commented Jan 7, 2026

Should this be optional opt-in / out?

@mattapperson
Copy link
Copy Markdown
Collaborator Author

@seawatts I don't think so, this is just fixing he conversion of zod to what our api needs

Comment thread src/lib/tool-executor.ts
Comment thread src/lib/tool-executor.ts Outdated
louisgv
louisgv previously approved these changes Jan 7, 2026
Copy link
Copy Markdown
Member

@louisgv louisgv left a comment

Choose a reason for hiding this comment

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

lgtm beside the null cast issue

Address PR feedback about unsafe `as Record<string, unknown>` cast
that could hide null returns. Now uses:
- Function overloads to preserve type information
- isNonNullObject typeguard for safe type narrowing
@mattapperson mattapperson merged commit 943466b into main Jan 7, 2026
1 check passed
@mattapperson mattapperson deleted the fix/zod-v4-standard-schema-sanitization branch January 7, 2026 19:02
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 v4's toJSONSchema() includes hidden ~standard property causing 400 errors with downstream providers

4 participants