zod: Allow Custom Errors on any value?
Any reason not to allow defining the last argument for any value as an error message to allow overriding the error message for that property easily? The current method is not really ideal, especially when you have many string props but need different errors.
A couple nice ways to handle it:
Allow Last Param to be Error Message
Would also accept a custom error that it would throw instead of ZodError (similar to Joi)
const TestSchema = z.object({
three: z.literal('hi').optional(),
one: z.number(),
two: z.literal(3, 'that isnt 3 dummy'),
four: z.string('string not whatever you gave!'),
five: z.date()
})
Add a .error() option like Joi
const TestSchema = z.object({
three: z.literal('hi').optional(),
one: z.number(),
two: z.literal(3).error(new Error('that isnt 3 dummy')),
four: z.string().optional().error(new Error('string not whatever you gave!')),
five: z.date()
})
For the VSCode extension I am working on, these styles add the benefit that jsdoc can be used to transfer over error messaging easily:

About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 35
- Comments: 32 (9 by maintainers)
This is on the roadmap. Though it’ll likely be an object instead of a string to leave room for future API additions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
What about yup#setLocale API? It seems to be easier to handle global translations for both primitives and their methods
Zod brought me out of two days of depression after going through several other libraries.
At the moment this is the only problem I have encountered. Against the background of everything else, this is a mere trifle, but nevertheless I am also waiting for a solution to this problem.
Zod is really super cool, but I also stumbled upon this issue here while figuring out how to use React Hook Form resolvers together with localized error messages using i18next. The API with a
messageproperty (likez.string().min(5, { message: "Must be 5 or more characters long" })is quite ok, but it must be possible to pass in an object as a message. Otherwise, it won’t be possible to translate complex messages with interpolations in them. Is this still planned?I’m also looking forward to this - I’m using
zodin forms, and if a user fails to enter a required field, i’d rather it say something like “X is required” instead ofExpected number, received nan, but at the moment I don’t see a good way to add that requiremnet.Hmmm just stumbled upon a usecase where we need a custom error for invalid_literal values when checking literals. 😕
Let me share my latest workaround for this (updated since May 17):
Example usage:
I think the issue with ZodErrorMap is theres often cases where you want a certain schema to return a different error for that specific schema. The limit of having only a message object in the granular case precludes you from having error objects returned by zod, for later parsing by an application to react to those errors. E.g. being able to return an object of an arbitary shape.
Ultimately, only being able to return a message string in the non-global case precludes you from having custom errors for a schema where you want to do i18n later or if you need to react to those errors based on some key in your application for whatever reason. Lets say if you wanted to provide a button to the user to help them fix a certain error type. Tbh, I do think these use cases are mostly Ui based.
I’d suggest what would solve this is something like:
I’ll add that you can workaround this now by serialising your custom error obj into the message key but thats obviously very dirty. You also dont have access to the
pathso have to repeat it in your error obj.Also want to use the opportunity to express how great this library is. Its actually fantastic to be able to write a schema and infer the type for use in a form lib like Formik. Really great stuff that deserves attention.
@osdiab you can globally modify every error Zod creates with Error Maps: https://github.com/colinhacks/zod/blob/master/ERROR_HANDLING.md#customizing-errors-with-zoderrormap
Until I find a better solution, I implemented the following workaround in my code:
The trick is to defer the evaluation of the
t()function until the string is printed which could have also been achieved if zod accepted a function as a message.What if the schema is defined on a per-form basis (e.g react-hook-form) and I need to localize error messages (react-i18next).
Similar to
yupwhich have a community driven package: yup-localesIn my case given that the error happens at the
number()stage I just want to be able to do this:or alternatively for more complicated circumstances,
To me this is a logical UX choice, but I haven’t been using Zod for that long so I could be missing something that makes this impractical.
I have created a PR #543 that your could set
requiredorinvalidmessages to string, number and boolean. Would like to hear from you guys on ways to improve it.I’ve been trying to create schema with i18n error messages. Ended up on this solution:
Hope it might help someone
As @maxArturo said, this has been mostly implemented for a long time now - whoops. Almost every schema creation function
z.whateversupports an options object with therequired_errorandinvalid_type_erroroptions.This is true for all schema types.
You can set an error map globally with
z.setErrorMap.You can set an error map on a per-schema basis
And you can set a contextual error map in a particular call to
.parse.Tracked in other issues. #1622
Closing. If the set of current offering doesn’t cover a particular use case, another issue can be opened.
Hi all! This seems to be one of the oldest open issues in the repo, and the original header issue title seems to have been resolved some time ago with custom errors and
errorMaps.However there are some additional asks that seem very useful and probably merit their own issues. Would it be better to open separate issues on these topics and discuss/track progress there instead? I took a quick look but couldn’t find a great home for the following:
schema.parse()(@osdiab / @adam-thomas-privitar )Let me know your thoughts! 🙏
Landed here while working on an issue today where my react app with i18next translated literals were not getting used. I tried @vsimko’s solution, but found it didn’t work with i18next-parser (which I’m using to extract translations). The root issue is that the schema is created before i18next gets initialized (I’m doing so in a hook in the root component). I found an easy alternative which is to just move the schema code and its type inside of the component:
Previously, my schema object and type were above the LoginForm component itself and I only got the default messages. Now I have full type safety and localized validation messages, which is awesome. Hope this helps someone else.