{"record":{"id":"a9e5456a5222c736","repo":"colinhacks/zod","slug":"unrecognized-hash-format-format","errorCode":null,"errorMessage":"Unrecognized hash format: ${format}","messagePattern":"Unrecognized hash format: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/classic/schemas.ts","lineNumber":1022,"sourceCode":"\nexport function hostname(_params?: string | core.$ZodStringFormatParams): ZodCustomStringFormat<\"hostname\"> {\n  return core._stringFormat(ZodCustomStringFormat, \"hostname\", core.regexes.hostname, _params) as any;\n}\n\nexport function hex(_params?: string | core.$ZodStringFormatParams): ZodCustomStringFormat<\"hex\"> {\n  return core._stringFormat(ZodCustomStringFormat, \"hex\", core.regexes.hex, _params) as any;\n}\n\nexport function hash<Alg extends util.HashAlgorithm, Enc extends util.HashEncoding = \"hex\">(\n  alg: Alg,\n  params?: {\n    enc?: Enc;\n  } & core.$ZodStringFormatParams\n): ZodCustomStringFormat<`${Alg}_${Enc}`> {\n  const enc = params?.enc ?? \"hex\";\n  const format = `${alg}_${enc}` as const;\n  const regex = core.regexes[format as keyof typeof core.regexes] as RegExp;\n  if (!regex) throw new Error(`Unrecognized hash format: ${format}`);\n  return core._stringFormat(ZodCustomStringFormat, format, regex, params) as any;\n}\n\n// ZodNumber\nexport interface _ZodNumber<Internals extends core.$ZodNumberInternals = core.$ZodNumberInternals>\n  extends _ZodType<Internals> {\n  gt(value: number, params?: string | core.$ZodCheckGreaterThanParams): this;\n  /** Identical to .min() */\n  gte(value: number, params?: string | core.$ZodCheckGreaterThanParams): this;\n  min(value: number, params?: string | core.$ZodCheckGreaterThanParams): this;\n  lt(value: number, params?: string | core.$ZodCheckLessThanParams): this;\n  /** Identical to .max() */\n  lte(value: number, params?: string | core.$ZodCheckLessThanParams): this;\n  max(value: number, params?: string | core.$ZodCheckLessThanParams): this;\n  /** Consider `z.int()` instead. This API is considered *legacy*; it will never be removed but a better alternative exists. */\n  int(params?: string | core.$ZodCheckNumberFormatParams): this;\n  /** @deprecated This is now identical to `.int()`. Only numbers in the safe integer range are accepted. */\n  safe(params?: string | core.$ZodCheckNumberFormatParams): this;","sourceCodeStart":1004,"sourceCodeEnd":1040,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/classic/schemas.ts#L1004-L1040","documentation":"Thrown by z.hash(alg, params) when the constructed format key `${alg}_${enc}` does not resolve to an entry in core.regexes. Only the five algorithms md5/sha1/sha256/sha384/sha512 crossed with the three encodings hex/base64/base64url are predefined (15 keys). Any other combination — a typo, a future algorithm, or a custom encoding — has no matching regex and is rejected at schema-construction time.","triggerScenarios":"Calling z.hash('sha128') or z.hash('sha256', { enc: 'utf8' }). Using a string variable typed loosely (via `as any` or plain JS) so the compiler cannot catch an invalid algorithm/encoding pair.","commonSituations":"Assuming blake2/argon2/sha3 are supported because they exist in other libraries. Copying an algorithm name from a hash output label that differs from the registry key. JavaScript (non-TS) callers passing arbitrary strings.","solutions":["Use one of the supported pairs: algorithm in {md5, sha1, sha256, sha384, sha512} and encoding in {hex, base64, base64url}.","For an unsupported algorithm, register a custom string format with z.stringFormat() (or config.z.stringFormat) supplying your own RegExp instead of z.hash().","If the value comes from config/user input, validate it against the allowed set before passing it to z.hash()."],"exampleFix":"// before (throws — sha3 not registered)\nconst h = z.hash('sha3_256');\n\n// after (supported algorithm)\nconst h = z.hash('sha256');\n\n// or: register a custom format for an unsupported algorithm\nz.stringFormat('sha3_256', /^[0-9a-fA-F]{64}$/);","handlingStrategy":"validation","validationCode":"const HASH_ALGS = ['md5', 'sha1', 'sha256', 'sha384', 'sha512'];\nconst HASH_ENCODINGS = ['hex', 'base64', 'base64url'];\nfunction assertHashFormat(alg, enc = 'hex') {\n  if (!HASH_ALGS.includes(alg) || !HASH_ENCODINGS.includes(enc)) {\n    throw new Error(`Unsupported hash format: ${alg}_${enc}`);\n  }\n}\n\nassertHashFormat(userAlg, userEnc);\nconst Schema = z.hash(userAlg, { enc: userEnc });","typeGuard":"function isHashAlgorithm(v) {\n  return typeof v === 'string' && ['md5', 'sha1', 'sha256', 'sha384', 'sha512'].includes(v);\n}","tryCatchPattern":"try {\n  const Schema = z.hash(alg, { enc });\n} catch (e) {\n  if (e.message.startsWith('Unrecognized hash format')) {\n    // fall back to a registered custom stringFormat or reject the input\n    throw new Error(`Unsupported hash format '${alg}_${enc}'; supported: md5/sha1/sha256/sha384/sha512 x hex/base64/base64url`);\n  }\n  throw e;\n}","preventionTips":["If the algorithm/encoding come from config or user input, validate against the fixed allow-list before calling z.hash().","In TypeScript, avoid casting to `as any`; let the HashAlgorithm/HashEncoding union types catch typos at compile time.","Keep a unit test enumerating every supported pair so regressions surface early."],"tags":["hash","string-format","schema-construction","validation"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}