colinhacks/zod · error · Error
Can't use "invalid_type_error" or "required_error" in conjun
Error message
Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.
What it means
Thrown by processCreateParams when a schema is constructed with both a custom `errorMap` and one of `invalid_type_error` or `required_error` in the same params object. These are mutually exclusive because invalid_type_error/required_error compile down into an implicit errorMap, so supplying both is ambiguous.
Source
Thrown at packages/zod/src/v3/types.ts:127
export type RawCreateParams =
| {
errorMap?: ZodErrorMap | undefined;
invalid_type_error?: string | undefined;
required_error?: string | undefined;
message?: string | undefined;
description?: string | undefined;
}
| undefined;
export type ProcessedCreateParams = {
errorMap?: ZodErrorMap | undefined;
description?: string | undefined;
};
function processCreateParams(params: RawCreateParams): ProcessedCreateParams {
if (!params) return {};
const { errorMap, invalid_type_error, required_error, description } = params;
if (errorMap && (invalid_type_error || required_error)) {
throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);
}
if (errorMap) return { errorMap: errorMap, description };
const customMap: ZodErrorMap = (iss, ctx) => {
const { message } = params;
if (iss.code === "invalid_enum_value") {
return { message: message ?? ctx.defaultError };
}
if (typeof ctx.data === "undefined") {
return { message: message ?? required_error ?? ctx.defaultError };
}
if (iss.code !== "invalid_type") return { message: ctx.defaultError };
return { message: message ?? invalid_type_error ?? ctx.defaultError };
};
return { errorMap: customMap, description };
}
export type SafeParseSuccess<Output> = {View on GitHub (pinned to 912f0f51b0)
Solutions
- Pick one strategy: either keep errorMap and delete invalid_type_error/required_error, or drop errorMap and use the string params.
- If you need both behaviours, encode invalid_type_error/required_error logic inside your custom errorMap (return your message for code 'invalid_type' and when ctx.data is undefined).
- Audit every schema factory call in the affected module for the conflicting keys.
Example fix
// before
z.string({
errorMap: myErrorMap,
invalid_type_error: "Must be a string",
required_error: "Required",
});
// after
z.string({ errorMap: myErrorMap });
// or, encode the same messages inside myErrorMap:
const myErrorMap = (iss, ctx) => {
if (typeof ctx.data === "undefined") return { message: "Required" };
if (iss.code === "invalid_type") return { message: "Must be a string" };
return { message: ctx.defaultError };
}; Defensive patterns
Strategy: validation
Validate before calling
function checkParams(p: RawCreateParams) {
if (p && p.errorMap && (p.invalid_type_error || p.required_error)) {
throw new Error("Remove invalid_type_error/required_error when using errorMap");
}
}
// call before z.X(..., params) Type guard
function isExclusiveErrorParams(
p: RawCreateParams
): p is { errorMap: NonNullable<RawCreateParams> extends never ? never : any } {
return !!p?.errorMap && !p.invalid_type_error && !p.required_error;
} Try / catch
try { const s = z.string(params); }
catch (e) { /* surface to schema author: pick one error strategy */ } Prevention
- Standardise on a single error strategy per module (all errorMap or all string params).
- Wrap schema construction in a factory that enforces the mutual exclusion.
- Lint for params objects containing both keys.
When it happens
Trigger: Calling a schema factory like `z.string({ errorMap: myMap, invalid_type_error: "..." })` or `z.object({...}, { errorMap, required_error })`. Any v3 schema creator that accepts RawCreateParams can hit it.
Common situations: Migrating per-field string error messages to a shared errorMap and forgetting to remove the old strings; copy-pasting params from one schema to another; mixing a global setErrorMap-style helper with inline string overrides.
Related errors
- You must pass an array of schemas to z.tuple([ ... ])
- Synchronous parse encountered promise.
- A discriminator value for key `${discriminator}` could not b
- Discriminator property ${String(discriminator)} has duplicat
- Async refinement encountered during synchronous parse operat
AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03).
Data as JSON: /data/errors/f83bba4bec81e8c0.json.
Report an issue: GitHub.