Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Zod · Module

.refine

.refine() adds custom validation to any Zod schema. Its predicate passes on truthy results and reports a custom issue on falsy results, with optional error and continuation settings.

How it works

Call .refine on a schema when validation needs a custom predicate beyond Zod's built-in checks. A truthy predicate result accepts the value; a falsy result adds a custom validation issue, optionally configured with an error message, path, or abort behavior.

Syntax

.refine(validator: (data: T) => any, params?: RefineParams)

Parameters

NameTypeDescription
validator(data: T) => anyA predicate receiving the value inferred by the schema; truthy results pass and falsy results fail.
paramsRefineParamsOptional refinement configuration such as an error message, error path, parameters, or abort behavior.

Returns

A new schema containing the refinement; parsing succeeds only when the predicate returns a truthy value.

Key points

  • Refinements are attached to schemas and extend validation with custom rules.
  • Use refine for domain constraints that are not covered by a built-in Zod check.
  • The abort option controls whether validation continues after this check fails.
  • A normal refine failure is represented as one custom issue.

Common mistakes

  • Do not throw from the predicate; return a truthy or falsy result instead.
  • Exceptions from the predicate escape Zod rather than becoming validation issues.
  • Set abort when later checks should not run after this refinement fails.
  • Use superRefine instead when one validation needs multiple issues or specific issue types.

Example: Add a custom username check

import { z } from "zod";

const username = z.string()
  .min(3)
  .refine((value) => value === value.toLowerCase(), {
    error: "Must be lowercase",
    abort: true,
  });

console.log(username.safeParse("alice").success); // true
console.log(username.safeParse("Al").success); // false

The schema first applies the built-in length check, then uses refine for a custom lowercase requirement.

When to use it

Custom business validation

Enforce a domain rule that has no direct built-in Zod check.

Customized validation feedback

Attach a targeted message or location to a failed custom check.

Short-circuit validation

Stop dependent checks after an earlier refinement fails.

Interview questions

QWhat does .refine do?

refine attaches custom validation to an existing schema. Its predicate receives the schema's inferred value, and truthy results pass while falsy results produce a validation issue.

Follow-up: How would you report several distinct failures? Use superRefine, which can create multiple issues and use Zod's internal issue types.

QWhat can the second argument configure?

The second argument configures the failure, including an error message and an optional path appended to the error location. Current Zod also supports abort to stop validation after that check fails.

Follow-up: When is abort useful? Use it when subsequent checks depend on the refinement or should not execute after failure.

QWhen should you use superRefine instead?

refine is intended for a single custom validation issue. superRefine is the more capable alternative when validation must emit multiple issues or customize their issue codes.

Follow-up: Does a predicate need to return boolean? No; any truthy value passes and any falsy value fails.

  • superRefine
  • error
  • abort
  • path

Source: Defining schemas | Zod. Checked 2026-10-15.