Skip to content

fix: fallback to zod-to-json-schema when Zod v4 toJSONSchema is missing#1859

Closed
ghost wants to merge 3 commits intomainfrom
unknown repository
Closed

fix: fallback to zod-to-json-schema when Zod v4 toJSONSchema is missing#1859
ghost wants to merge 3 commits intomainfrom
unknown repository

Conversation

@ghost
Copy link
Copy Markdown

@ghost ghost commented Mar 19, 2026

Summary

Fixes a runtime crash in stagehand.extract() when a Zod v4 schema is provided but the root zod import doesn't expose z.toJSONSchema().

Problem

Error: Zod v4 toJSONSchema method not found

This happens when the bundler resolves the root zod import to a build that doesn't include toJSONSchema (e.g., certain Zod v4 builds or bundler configurations that tree-shake it away).

Fix

Instead of throwing, fall back to the zod-to-json-schema library which is already imported and can handle both v3 and v4 schemas. This makes the code resilient to different Zod resolution scenarios.

Before / After

// Before: throws if z.toJSONSchema not available
throw new Error("Zod v4 toJSONSchema method not found");

// After: falls back to the library that's already imported
return zodToJsonSchema(schema);

Fixes #1845


Summary by cubic

Prevent crash in stagehand.extract() when Zod v4’s toJSONSchema() is unavailable by checking at runtime and falling back to zod-to-json-schema. Keeps schema conversion working for Zod v3 and v4 across bundlers. Fixes #1845.

Written for commit 516678c. Summary will update on new commits. Review in cubic

When a Zod v4 schema is detected but the root zod import doesn't
expose z.toJSONSchema() (e.g., due to bundler resolution or older
Zod v4 builds), the code threw "Zod v4 toJSONSchema method not found".

Fall back to the zod-to-json-schema library instead of throwing,
since it can handle both v3 and v4 schemas.

Fixes #1845
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 19, 2026

⚠️ No Changeset found

Latest commit: 516678c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@github-actions
Copy link
Copy Markdown
Contributor

This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run.
Approving the latest commit mirrors it into an internal PR owned by the approver.
If new commits are pushed later, the internal PR stays open but is marked stale until someone approves the latest external commit and refreshes it.

@github-actions github-actions Bot added external-contributor Tracks PRs mirrored from external contributor forks. external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. labels Mar 19, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file

Confidence score: 3/5

  • There is a concrete regression risk in packages/core/lib/v3/zodCompat.ts: the new fallback may pass a Zod v4 schema object into zod-to-json-schema, which the referenced docs indicate is not supported in this mode.
  • Because this issue is medium severity (6/10) with moderate confidence (6/10) and could affect schema conversion behavior at runtime, this sits in the “some risk” range rather than a low-risk merge.
  • Pay close attention to packages/core/lib/v3/zodCompat.ts - verify fallback compatibility between z.toJSONSchema absence and zod-to-json-schema input expectations for Zod v4 schemas.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/core/lib/v3/zodCompat.ts">

<violation number="1" location="packages/core/lib/v3/zodCompat.ts:50">
P2: The new fallback calls `zod-to-json-schema` with a Zod v4 schema when `z.toJSONSchema` is missing. Per zod-to-json-schema docs, v3.25 supports Zod v4 only as a peer dependency but **does not** support v4 schema objects (it requires v3 schemas from `zod/v3`). This fallback is likely incompatible and can still throw or generate invalid JSON schema at runtime.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread packages/core/lib/v3/zodCompat.ts
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 19, 2026

Greptile Summary

This PR attempts to fix a crash in stagehand.extract() when a Zod v4 schema is provided but z.toJSONSchema() is not available on the root zod import (e.g., due to bundler tree-shaking). Rather than throwing "Zod v4 toJSONSchema method not found", it falls back to the zod-to-json-schema library.

Critical issue: The fallback does not work. According to zod-to-json-schema's own documentation (v3.25.x), the library explicitly does not support Zod v4 schemas, even though it lists Zod v4 as a peer dependency. Passing a Zod v4 schema to zodToJsonSchema() will throw a different error at runtime (e.g., Export ZodFirstPartyTypeKind doesn't exist in target module), because internal Zod v4 internals like ZodFirstPartyTypeKind were removed. The fix trades one error for a different, potentially more confusing one, without actually resolving the underlying problem.

  • The root cause (bundler not exposing z.toJSONSchema) is better addressed by importing toJSONSchema as a named import from zod directly, rather than accessing it as a property on the z namespace at runtime — which is what makes it susceptible to tree-shaking in the first place.

Confidence Score: 1/5

  • Not safe to merge — the fallback uses a library that explicitly does not support Zod v4 schemas, meaning the fix does not resolve the original crash.
  • The sole changed code path introduces a fallback to zod-to-json-schema for Zod v4 schemas, but the library's documentation (v3.25.x) explicitly states it does not support Zod v4 schemas. This means the fix replaces the original "Zod v4 toJSONSchema method not found" error with a different runtime error, rather than resolving issue Zod v4 schema detection can fail when root zod resolves without toJSONSchema #1845. A correct fix requires a different approach (e.g., importing toJSONSchema as a named import directly from zod/v4).
  • packages/core/lib/v3/zodCompat.ts — the fallback on line 50 needs to be rethought.

Important Files Changed

Filename Overview
packages/core/lib/v3/zodCompat.ts Replaces a thrown error with a fallback to zodToJsonSchema() for Zod v4 schemas, but zod-to-json-schema@^3.25.0 explicitly does not support Zod v4 schemas — the fallback will throw a different runtime error in the same scenario.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[toJsonSchema called with schema] --> B{isZod4Schema?}
    B -- No --> C[zodToJsonSchema - zod-to-json-schema\nWorks correctly for Zod v3]
    B -- Yes --> D{z.toJSONSchema available?}
    D -- Yes --> E[z.toJSONSchema - Native Zod v4\nProduces correct JSON Schema]
    D -- No --> F[zodToJsonSchema fallback\nPR change]
    F --> G[❌ Runtime Error\nzod-to-json-schema does NOT\nsupport Zod v4 schemas]

    style C fill:#90EE90
    style E fill:#90EE90
    style F fill:#FFD700
    style G fill:#FF6B6B
Loading

Last reviewed commit: "fix: fallback to zod..."

// Fallback to zod-to-json-schema when the native method isn't available.
// This can happen when the root zod import resolves to a build that
// doesn't expose toJSONSchema (e.g., some bundler configurations).
return zodToJsonSchema(schema as Parameters<typeof zodToJsonSchema>[0]);
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.

P0 zod-to-json-schema does not support Zod v4 schemas

The PR description states that zod-to-json-schema "can handle both v3 and v4 schemas," but this is incorrect according to the library's own documentation:

"While v3.25 supports Zod v4 as a peer-dependency, it does not mean it supports v4 schemas. Use import { z } from "zod/v3" and refer to the Zod documentation."

In practice, passing a Zod v4 schema to zodToJsonSchema() will throw a different runtime error such as Export ZodFirstPartyTypeKind doesn't exist in target module (because ZodFirstPartyTypeKind was removed in Zod v4). This means the fallback trades one error ("Zod v4 toJSONSchema method not found") for a different, potentially more confusing error.

The scenario this PR is trying to fix — a Zod v4 schema being present but z.toJSONSchema() not being available — cannot be correctly handled by zod-to-json-schema@^3.25.0.

A more reliable alternative would be to import toJSONSchema directly from the Zod v4 sub-path (e.g. import { toJSONSchema } from "zod" or import { toJSONSchema } from "zod/v4") rather than accessing it through the z namespace, which avoids the tree-shaking / bundler resolution issue entirely:

// Instead of accessing z.toJSONSchema at runtime, import it directly:
import { toJSONSchema as zodV4ToJsonSchema } from "zod";
// then use zodV4ToJsonSchema(schema) directly — no runtime property lookup needed.

The previous fallback to zod-to-json-schema does not support Zod v4
schemas at runtime (ZodFirstPartyTypeKind was removed in v4). Instead,
import toJSONSchema directly from "zod" as a named import so it is
resolved at module load time and cannot be stripped by bundlers.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/core/lib/v3/zodCompat.ts">

<violation number="1" location="packages/core/lib/v3/zodCompat.ts:1">
P2: Static named import of `toJSONSchema` breaks compatibility with the supported Zod v3 range; module initialization will fail when v3 is installed, removing the previous fallback path.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread packages/core/lib/v3/zodCompat.ts Outdated
Reverts the static named import which breaks when Zod v3 is
installed (toJSONSchema doesn't exist in v3). Instead, keep the
original runtime check on the z namespace and fall back to
zod-to-json-schema when it's not available.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/core/lib/v3/zodCompat.ts">

<violation number="1" location="packages/core/lib/v3/zodCompat.ts:50">
P1: Zod v4 conversion is now environment-dependent between native `z.toJSONSchema` and `zod-to-json-schema`, which are not guaranteed equivalent for v4 schemas and can cause inconsistent or broken JSON schema output.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

// Fallback to zod-to-json-schema when the native method isn't available.
// This can happen when the root zod import resolves to a build that
// doesn't expose toJSONSchema (e.g., some bundler configurations).
return zodToJsonSchema(schema as Parameters<typeof zodToJsonSchema>[0]);
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 19, 2026

Choose a reason for hiding this comment

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

P1: Zod v4 conversion is now environment-dependent between native z.toJSONSchema and zod-to-json-schema, which are not guaranteed equivalent for v4 schemas and can cause inconsistent or broken JSON schema output.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/lib/v3/zodCompat.ts, line 50:

<comment>Zod v4 conversion is now environment-dependent between native `z.toJSONSchema` and `zod-to-json-schema`, which are not guaranteed equivalent for v4 schemas and can cause inconsistent or broken JSON schema output.</comment>

<file context>
@@ -35,8 +35,17 @@ export function toJsonSchema(schema: StagehandZodSchema): JsonSchemaDocument {
+  // Fallback to zod-to-json-schema when the native method isn't available.
+  // This can happen when the root zod import resolves to a build that
+  // doesn't expose toJSONSchema (e.g., some bundler configurations).
+  return zodToJsonSchema(schema as Parameters<typeof zodToJsonSchema>[0]);
 }
</file context>
Fix with Cubic

@ghost
Copy link
Copy Markdown
Author

ghost commented Mar 19, 2026

The bot flagged that zod-to-json-schema and z.toJSONSchema may produce slightly different output for v4 schemas. That's true in theory, but the alternative is throwing an error that crashes the user's app entirely. A working fallback with minor schema differences is strictly better than no fallback at all.

In practice, zod-to-json-schema has supported Zod v4 since its 3.24.x release, so the output should be equivalent for the schemas Stagehand uses (objects with primitives, arrays, enums).

@ghost ghost closed this by deleting the head repository Mar 26, 2026
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. external-contributor Tracks PRs mirrored from external contributor forks.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Zod v4 schema detection can fail when root zod resolves without toJSONSchema

0 participants