Cross-field validation
A form or API object has related fields whose combined values must satisfy a rule.
Zod · Type Alias
RefinementCtx is the context passed to custom refinement callbacks. Use it to record validation issues and associate them with locations in the parsed data.
RefinementCtx is the context object passed to refinement callbacks. In current Zod, refinement-style callbacks use it to report validation failures by adding issues, including a path that identifies the problematic part of the input.
(value, ctx) => { /* use ctx.issues */ }import { z } from "zod";
const User = z.object({
password: z.string(),
confirmPassword: z.string(),
}).superRefine((data, ctx) => {
if (data.password !== data.confirmPassword) {
ctx.addIssue({
code: "custom",
path: ["confirmPassword"],
message: "Passwords do not match",
});
}
});
console.log(User.safeParse({
password: "secret",
confirmPassword: "different",
}).success);Uses the refinement context supplied to superRefine to add a targeted validation issue.
A form or API object has related fields whose combined values must satisfy a rule.
One input can violate several independent business constraints.
An error should point to a nested property rather than the whole object.
RefinementCtx is the callback context available while custom validation runs. It lets the callback communicate validation failures to Zod by recording issues, including their messages and paths.
Follow-up: How can a refinement report multiple failures? Add multiple issue objects to the context's issue collection during one callback.
Use the context to attach an issue to a specific location in structured input. For example, a cross-field check can identify the field that should receive the error.
Follow-up: How would you associate an issue with a nested property? Set the issue path to the nested property's path segments.
Zod's regular refine API produces one custom issue, while the more flexible refinement callback can create issues with internal issue types. The context is the mechanism used to communicate those issues.
Follow-up: What should validation code do instead of throwing? Return normally and record a validation issue in the context.
refinesuperRefinectx.issuesZodIssueabortwhen