{"record":{"id":"f83bba4bec81e8c0","repo":"colinhacks/zod","slug":"can-t-use-invalid-type-error-or-required-error","errorCode":null,"errorMessage":"Can't use \"invalid_type_error\" or \"required_error\" in conjunction with custom error map.","messagePattern":"Can't use \"invalid_type_error\" or \"required_error\" in conjunction with custom error map\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v3/types.ts","lineNumber":127,"sourceCode":"\nexport type RawCreateParams =\n  | {\n      errorMap?: ZodErrorMap | undefined;\n      invalid_type_error?: string | undefined;\n      required_error?: string | undefined;\n      message?: string | undefined;\n      description?: string | undefined;\n    }\n  | undefined;\nexport type ProcessedCreateParams = {\n  errorMap?: ZodErrorMap | undefined;\n  description?: string | undefined;\n};\nfunction processCreateParams(params: RawCreateParams): ProcessedCreateParams {\n  if (!params) return {};\n  const { errorMap, invalid_type_error, required_error, description } = params;\n  if (errorMap && (invalid_type_error || required_error)) {\n    throw new Error(`Can't use \"invalid_type_error\" or \"required_error\" in conjunction with custom error map.`);\n  }\n  if (errorMap) return { errorMap: errorMap, description };\n  const customMap: ZodErrorMap = (iss, ctx) => {\n    const { message } = params;\n\n    if (iss.code === \"invalid_enum_value\") {\n      return { message: message ?? ctx.defaultError };\n    }\n    if (typeof ctx.data === \"undefined\") {\n      return { message: message ?? required_error ?? ctx.defaultError };\n    }\n    if (iss.code !== \"invalid_type\") return { message: ctx.defaultError };\n    return { message: message ?? invalid_type_error ?? ctx.defaultError };\n  };\n  return { errorMap: customMap, description };\n}\n\nexport type SafeParseSuccess<Output> = {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v3/types.ts#L109-L145","documentation":"Thrown by processCreateParams at packages/zod/src/v3/types.ts:127 when a schema factory is given both a custom errorMap AND either invalid_type_error or required_error in the same params object. These are two mutually exclusive ways to customize messages — errorMap is the general callback form, while invalid_type_error/required_error are shorthand shortcuts — so Zod refuses to guess which one wins. The check happens at schema construction time, before any data is parsed.","triggerScenarios":"Calling a schema factory like `z.string({ errorMap: myMap, invalid_type_error: '...' })` or `z.object({...}, { errorMap: myMap, required_error: '...' })` — i.e. passing both errorMap and one of the shorthand message options together in the second-argument params.","commonSituations":"Adding invalid_type_error/required_error to an existing schema that already uses a global or local errorMap; copy-pasting params from another schema that had an errorMap; migrating from per-field messages to a shared errorMap and leaving the shorthand keys behind; using z.setErrorMap globally and then also passing shorthand params.","solutions":["Pick one mechanism: keep errorMap and remove invalid_type_error/required_error from the params object.","Or drop errorMap and use only invalid_type_error/required_error for the two targeted messages.","If you need both targeted messages and a custom map, fold the special-case logic into your errorMap callback (branch on iss.code === 'invalid_type' and typeof ctx.data === 'undefined').","Audit the params object passed to the factory — including ones spread from a shared config — for leftover shorthand keys."],"exampleFix":"// before\nconst schema = z.string({\n  errorMap: myErrorMap,\n  invalid_type_error: 'Expected a string',\n  required_error: 'String is required',\n});\n\n// after (fold logic into the error map)\nconst schema = z.string({\n  errorMap: (iss, ctx) => {\n    if (iss.code === 'invalid_type') return { message: 'Expected a string' };\n    if (typeof ctx.data === 'undefined') return { message: 'String is required' };\n    return { message: ctx.defaultError };\n  },\n});","handlingStrategy":"validation","validationCode":"import type { RawCreateParams } from 'zod';\n\nfunction assertCleanParams(params: RawCreateParams): RawCreateParams {\n  if (!params) return params;\n  const hasShorthand = 'invalid_type_error' in params || 'required_error' in params;\n  const hasErrorMap = 'errorMap' in params && params.errorMap !== undefined;\n  if (hasShorthand && hasErrorMap) {\n    throw new Error('Refusing to pass both errorMap and shorthand messages to Zod; remove one.');\n  }\n  return params;\n}\n\n// usage: z.string(assertCleanParams(config));","typeGuard":"function hasConflictingErrorParams(p: unknown): p is { errorMap: unknown; invalid_type_error?: unknown; required_error?: unknown } {\n  if (!p || typeof p !== 'object') return false;\n  const o = p as Record<string, unknown>;\n  const hasMap = typeof o.errorMap !== 'undefined';\n  const hasShorthand = typeof o.invalid_type_error !== 'undefined' || typeof o.required_error !== 'undefined';\n  return hasMap && hasShorthand;\n}","tryCatchPattern":"null","preventionTips":["Adopt one error-customisation style per schema: either errorMap OR shorthand messages, never both.","When spreading a shared config object into schema params, audit it for leftover shorthand keys.","Centralise error-message config in a factory so the conflict can't arise ad hoc.","Treat errorMap as the upgrade path: when you need more than invalid_type/required messages, migrate fully to errorMap."],"tags":["schema-construction","error-map","params","configuration"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}