💎 Zod 4 is now stable!  Read the announcement.
Zod logo

Personalización de errores

En Zod, los errores de validación aparecen como instancias de la clase z.core.$ZodError.

La clase ZodError en el paquete zod es una subclase que implementa algunos métodos de conveniencia adicionales.

Las instancias de $ZodError contienen un array .issues. Cada issue (problema) contiene un message legible por humanos y metadatos estructurados adicionales sobre el problema.

import * as z from "zod";
 
const result = z.string().safeParse(12); // { success: false, error: ZodError }
result.error.issues;
// [
//   {
//     expected: 'string',
//     code: 'invalid_type',
//     path: [],
//     message: 'Invalid input: expected string, received number'
//   }
// ]

Cada issue contiene una propiedad message con un mensaje de error legible por humanos. Los mensajes de error se pueden personalizar de varias maneras.

El parámetro error

Prácticamente todas las API de Zod aceptan un mensaje de error opcional.

z.string("Not a string!");

Este error personalizado aparecerá como la propiedad message de cualquier issue de validación que se origine en este esquema.

z.string("Not a string!").parse(12);
// ❌ throws ZodError {
//   issues: [
//     {
//       expected: 'string',
//       code: 'invalid_type',
//       path: [],
//       message: 'Not a string!'   <-- 👀 custom error message
//     }
//   ]
// }

Todas las funciones z y métodos de esquema aceptan errores personalizados.

z.string("Bad!");
z.string().min(5, "Too short!");
z.uuid("Bad UUID!");
z.iso.date("Bad date!");
z.array(z.string(), "Not an array!");
z.array(z.string()).min(5, "Too few items!");
z.set(z.string(), "Bad set!");

Si lo prefieres, puedes pasar un objeto de parámetros con un parámetro error en su lugar.

z.string({ error: "Bad!" });
z.string().min(5, { error: "Too short!" });
z.uuid({ error: "Bad UUID!" });
z.iso.date({ error: "Bad date!" });
z.array(z.string(), { error: "Bad array!" });
z.array(z.string()).min(5, { error: "Too few items!" });
z.set(z.string(), { error: "Bad set!" });

El parámetro error opcionalmente acepta una función. Una función de personalización de errores se conoce como un mapa de errores (error map) en la terminología de Zod. El mapa de errores se ejecutará en tiempo de análisis si ocurre un error de validación.

z.string({ error: ()=>`[${Date.now()}]: Validation failure.` });

Nota — En Zod v3, había parámetros separados para message (una cadena) y errorMap (una función). Estos se han unificado en Zod 4 como error.

El mapa de errores recibe un objeto de contexto que puedes usar para personalizar el mensaje de error basado en el issue de validación.

z.string({
  error: (iss) => iss.input === undefined ? "Field is required." : "Invalid input."
});

Para casos avanzados, el objeto iss proporciona información adicional que puedes usar para personalizar el error.

z.string({
  error: (iss) => {
    iss.code; // el código del issue
    iss.input; // los datos de entrada
    iss.inst; // el esquema/verificación que originó este issue
    iss.path; // la ruta del error
  },
});

Dependiendo de la API que estés usando, puede haber propiedades adicionales disponibles. Usa el autocompletado de TypeScript para explorar las propiedades disponibles.

z.string().min(5, {
  error: (iss) => {
    // ...lo mismo que arriba
    iss.minimum; // el valor mínimo
    iss.inclusive; // si el mínimo es inclusivo
    return `Password must have ${iss.minimum} characters or more`;
  },
});

Devuelve undefined para evitar personalizar el mensaje de error y volver al mensaje predeterminado. (Más específicamente, Zod cederá el control al siguiente mapa de errores en la cadena de precedencia.) Esto es útil para personalizar selectivamente ciertos mensajes de error pero no otros.

z.int64({
  error: (issue) => {
    // anular el mensaje de error too_big
    if (issue.code === "too_big") {
      return { message: `Value must be <${issue.maximum}` };
    }
 
    //  diferir al predeterminado
    return undefined;
  },
});

Personalización de errores por análisis

Para personalizar errores en una base por análisis, pasa un mapa de errores al método parse:

const schema = z.string();
 
schema.parse(12, {
  error: iss => "per-parse custom error"
});

Esto tiene menor precedencia que cualquier mensaje personalizado a nivel de esquema.

const schema = z.string({ error: "highest priority" });
const result = schema.safeParse(12, {
  error: (iss) => "lower priority",
});
 
result.error.issues;
// [{ message: "highest priority", ... }]

El objeto iss es una unión discriminada de todos los tipos de issues posibles. Usa la propiedad code para discriminar entre ellos.

Para un desglose de todos los códigos de issue de Zod, consulta la documentación de zod/v4/core.

const result = schema.safeParse(12, {
  error: (iss) => {
    if (iss.code === "invalid_type") {
      return `invalid type, expected ${iss.expected}`;
    }
    if (iss.code === "too_small") {
      return `minimum is ${iss.minimum}`;
    }
    // ...
  }
});

Incluir entrada en issues

Por defecto, Zod no incluye datos de entrada en los issues. Esto es para evitar el registro involuntario de datos de entrada potencialmente sensibles. Para incluir los datos de entrada en cada issue, usa la bandera reportInput:

z.string().parse(12, {
  reportInput: true
})
 
// ZodError: [
//   {
//     "expected": "string",
//     "code": "invalid_type",
//     "input": 12, // 👀
//     "path": [],
//     "message": "Invalid input: expected string, received number"
//   }
// ]

Personalización global de errores

Para especificar un mapa de errores global, usa z.config() para establecer la configuración customError de Zod:

z.config({
  customError: (iss) => {
    return "globally modified error";
  },
});

Los mensajes de error globales tienen menor precedencia que los mensajes de error a nivel de esquema o por análisis.

El objeto iss es una unión discriminada de todos los tipos de issues posibles. Usa la propiedad code para discriminar entre ellos.

Para un desglose de todos los códigos de issue de Zod, consulta la documentación de zod/v4/core.

z.config({
  customError: (iss) => {
    if (iss.code === "invalid_type") {
      return `invalid type, expected ${iss.expected}`;
    }
    if (iss.code === "too_small") {
      return `minimum is ${iss.minimum}`;
    }
    // ...
  },
});

Internacionalización

Para soportar la internacionalización de mensajes de error, Zod proporciona varias locales integradas. Estas se exportan desde el paquete zod/v4/core.

Nota — La biblioteca regular zod carga automáticamente la locale en. Zod Mini no carga ninguna locale por defecto; en su lugar, todos los mensajes de error tienen por defecto Invalid input.

import * as z from "zod";
import { en } from "zod/locales"
 
z.config(en());

Para cargar perezosamente (lazy load) una locale, considera importaciones dinámicas:

import * as z from "zod";
 
async function loadLocale(locale: string) {
  const { default: locale } = await import(`zod/v4/locales/${locale}.js`);
  z.config(locale());
};
 
await loadLocale("fr");

Por conveniencia, todas las locales se exportan como z.locales desde "zod". En algunos empaquetadores, esto puede no ser tree-shakable.

import * as z from "zod";
 
z.config(z.locales.en());

Locales

Las siguientes locales están disponibles:

  • ar — Arabic
  • az — Azerbaijani
  • be — Belarusian
  • bg — Bulgarian
  • ca — Catalan
  • cs — Czech
  • da — Danish
  • de — German
  • en — English
  • eo — Esperanto
  • es — Spanish
  • fa — Farsi
  • fi — Finnish
  • fr — French
  • frCA — Canadian French
  • he — Hebrew
  • hu — Hungarian
  • id — Indonesian
  • is — Icelandic
  • it — Italian
  • ja — Japanese
  • ka — Georgian
  • km — Khmer
  • ko — Korean
  • lt — Lithuanian
  • mk — Macedonian
  • ms — Malay
  • nl — Dutch
  • no — Norwegian
  • ota — Türkî
  • ps — Pashto
  • pl — Polish
  • pt — Portuguese
  • ru — Russian
  • sl — Slovenian
  • sv — Swedish
  • ta — Tamil
  • th — Thai
  • tr — Türkçe
  • uk — Ukrainian
  • ur — Urdu
  • vi — Tiếng Việt
  • zhCN — Simplified Chinese
  • zhTW — Traditional Chinese
  • yo — Yorùbá

Precedencia de errores

A continuación hay una referencia rápida para determinar la precedencia de errores: si se han definido múltiples personalizaciones de errores, ¿cuál tiene prioridad? De mayor a menor prioridad:

  1. Error a nivel de esquema — Cualquier mensaje de error "hard coded" en una definición de esquema.
z.string("Not a string!");
  1. Error por análisis — Un mapa de errores personalizado pasado al método .parse().
z.string().parse(12, {
  error: (iss) => "My custom error"
});
  1. Mapa de errores global — Un mapa de errores personalizado pasado a z.config().
z.config({
  customError: (iss) => "My custom error"
});
  1. Mapa de errores de locale — Un mapa de errores personalizado pasado a z.config().
z.config(z.locales.en());

On this page