fix: fallback to zod-to-json-schema when Zod v4 toJSONSchema is missing#1859
Conversation
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
|
|
This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run. |
There was a problem hiding this comment.
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 intozod-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 betweenz.toJSONSchemaabsence andzod-to-json-schemainput 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.
Greptile SummaryThis PR attempts to fix a crash in Critical issue: The fallback does not work. According to
Confidence Score: 1/5
Important Files Changed
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
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]); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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.
There was a problem hiding this comment.
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]); |
There was a problem hiding this comment.
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>
|
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). |
Summary
Fixes a runtime crash in
stagehand.extract()when a Zod v4 schema is provided but the rootzodimport doesn't exposez.toJSONSchema().Problem
This happens when the bundler resolves the root
zodimport to a build that doesn't includetoJSONSchema(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-schemalibrary which is already imported and can handle both v3 and v4 schemas. This makes the code resilient to different Zod resolution scenarios.Before / After
Fixes #1845
Summary by cubic
Prevent crash in
stagehand.extract()when Zod v4’stoJSONSchema()is unavailable by checking at runtime and falling back tozod-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