fix(transform): abort further processing when inner value is invalid
Previously when an inner value was invalid, transforms would not run, but subsequent refinements would still run with the non-transformed value, which in most cases would violate the typings.
This fix returns INVALID from the transform in case of a failed inner validation and stop outer refinements from running with the wrong types.
Closes #2243 Closes #2192 Closes #2113
Summary by CodeRabbit
- Tests
- Added a new test to verify behavior when a validation transform is skipped and an additional refinement is applied.
- Bug Fixes
- Improved handling of invalid parse results during schema transformations to ensure consistent error reporting.
Walkthrough
This update modifies the internal parsing logic for schema effects, specifically in how invalid intermediate results are handled during transforms. Now, when a validation fails before a transform, the parser returns a standardized INVALID constant rather than the original invalid result object. Additionally, new tests have been added to verify that the superRefine function is still called even when a transform is skipped due to earlier validation failure, ensuring consistent behavior across both test directories.
Changes
| File(s) | Change Summary |
|---|---|
| src/types.ts, deno/lib/types.ts | Updated ZodEffects._parse to return INVALID instead of the original invalid result when inner schema validation fails in a transform effect. Applies to both sync and async branches. No public API changes. |
| src/tests/refine.test.ts, deno/lib/tests/refine.test.ts | Added test "superRefine after skipped transform" to ensure superRefine is executed even if a transform is skipped due to validation failure. |
Sequence Diagram(s)
sequenceDiagram
participant User
participant Schema
participant Transform
participant SuperRefine
User->>Schema: parse(input)
Schema->>Schema: validate input (e.g., regex)
alt Validation fails
Schema-->>Transform: skip transform
Schema->>SuperRefine: call superRefine with original input
SuperRefine-->>Schema: add issues if needed
Schema-->>User: return INVALID result
else Validation passes
Schema->>Transform: apply transform
Transform->>SuperRefine: call superRefine with transformed value
SuperRefine-->>Schema: add issues if needed
Schema-->>User: return result
end
Assessment against linked issues
| Objective | Addressed | Explanation |
|---|---|---|
Prevent refine/superRefine from running when parser already failed (#2192, #2113, #2243) |
✅ | |
Ensure superRefine is still called after skipped transform, but with correct input (#2243) |
✅ | |
Avoid passing invalid or unexpected types to refine/superRefine when validation fails (#2192, #2113) |
✅ |
Poem
When transforms are skipped, but checks still remain,
The parser now signals withINVALID—so plain.
superRefinestands ready, no matter the fate,
Ensuring all rules, even after a gate.
With tests now in place and bugs out the door,
The schema’s more solid than ever before!
🛡️✨
📜 Recent review details
Configuration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between 9e3b4ed030c2df1d172e544d5408aa157526eefd and 354538fd45dd0d92b232e812d54a209551ff7e36.
📒 Files selected for processing (4)
deno/lib/__tests__/refine.test.ts(1 hunks)deno/lib/types.ts(2 hunks)src/__tests__/refine.test.ts(1 hunks)src/types.ts(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
deno/lib/types.ts (1)
deno/lib/helpers/parseUtil.ts (3)
isValid(187-188)INVALID(166-166)INVALID(167-169)
src/types.ts (1)
src/helpers/parseUtil.ts (3)
isValid(187-188)INVALID(166-166)INVALID(167-169)
🔇 Additional comments (6)
deno/lib/types.ts (2)
4727-4727: Handle invalid inner parse for sync transform
The new guardif (!isValid(base)) return INVALID;correctly aborts further processing when the inner parse is invalid in the synchronous branch, ensuring transform effects don’t run on invalid data.
4741-4741: Handle invalid inner parse for async transform
Matching the synchronous logic, the async branch now also returnsINVALIDif the base parse fails, keeping behavior consistent across both modes.src/types.ts (2)
727-728: Good fix to standardize error handling! 👍You're now returning the canonical
INVALIDconstant instead of the original invalid result when inner validation fails. This makes the transform failure behavior more consistent and prevents further processing with incorrect types.
741-742: Same fix applied to the async code path - nice!Consistent handling in both synchronous and asynchronous branches. This helps maintain predictable behavior regardless of how the parsing is performed.
src/__tests__/refine.test.ts (1)
308-322: Great test coverage for the fix! ✨This new test verifies that
superRefineruns even when a transform is skipped due to validation failure. It confirms the fix works as expected by trying to parse an empty string (which fails regex validation), causing the transform to be skipped, and ensuring proper behavior of the overall validation chain.deno/lib/__tests__/refine.test.ts (1)
309-323: Solid test mirroring for Deno environment! 👌Same test as added to the Node environment, ensuring consistent behavior across both runtimes. This is important for maintaining feature parity between the Node and Deno versions of the library.
✨ Finishing Touches
- [ ] 📝 Generate Docstrings
🪧 Tips
Chat
There are 3 ways to chat with CodeRabbit:
- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
I pushed a fix in commit <commit_id>, please review it.Generate unit testing code for this file.Open a follow-up GitHub issue for this discussion.
- Files and specific lines of code (under the "Files changed" tab): Tag
@coderabbitaiin a new review comment at the desired location with your query. Examples:@coderabbitai generate unit testing code for this file.@coderabbitai modularize this function.
- PR comments: Tag
@coderabbitaiin a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.@coderabbitai read src/utils.ts and generate unit testing code.@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.@coderabbitai help me debug CodeRabbit configuration file.
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.
CodeRabbit Commands (Invoked using PR comments)
@coderabbitai pauseto pause the reviews on a PR.@coderabbitai resumeto resume the paused reviews.@coderabbitai reviewto trigger an incremental review. This is useful when automatic reviews are disabled for the repository.@coderabbitai full reviewto do a full review from scratch and review all the files again.@coderabbitai summaryto regenerate the summary of the PR.@coderabbitai generate docstringsto generate docstrings for this PR.@coderabbitai generate sequence diagramto generate a sequence diagram of the changes in this PR.@coderabbitai resolveresolve all the CodeRabbit review comments.@coderabbitai configurationto show the current CodeRabbit configuration for the repository.@coderabbitai helpto get help.
Other keywords and placeholders
- Add
@coderabbitai ignoreanywhere in the PR description to prevent this PR from being reviewed. - Add
@coderabbitai summaryto generate the high-level summary at a specific location in the PR description. - Add
@coderabbitaianywhere in the PR title to generate the title automatically.
CodeRabbit Configuration File (.coderabbit.yaml)
- You can programmatically configure CodeRabbit by adding a
.coderabbit.yamlfile to the root of your repository. - Please see the configuration documentation for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation:
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
Documentation and Community
- Visit our Documentation for detailed information on how to use CodeRabbit.
- Join our Discord Community to get help, request features, and share feedback.
- Follow us on X/Twitter for updates and announcements.
Deploy Preview for guileless-rolypoly-866f8a ready!
Built without sensitive environment variables
| Name | Link |
|---|---|
| Latest commit | 354538fd45dd0d92b232e812d54a209551ff7e36 |
| Latest deploy log | https://app.netlify.com/sites/guileless-rolypoly-866f8a/deploys/6808bd00e9593e0008073d08 |
| Deploy Preview | https://deploy-preview-4266--guileless-rolypoly-866f8a.netlify.app |
| Preview on mobile | Toggle QR Code...Use your smartphone camera to open QR code link. |
To edit notification comments on pull requests, go to your Netlify site configuration.
@colinhacks Anything blocking this fix from being merged?
Thanks for the excellent PR and apologies it took so long. The codebase has changed under this PR so I ported this fix here: https://github.com/colinhacks/zod/pull/4554
Landed in [email protected]