{"record":{"id":"d3a2888ede6d9a5b","repo":"colinhacks/zod","slug":"invalid-hex-string-length","errorCode":null,"errorMessage":"Invalid hex string length","messagePattern":"Invalid hex string length","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/util.ts","lineNumber":965,"sourceCode":"    binaryString += String.fromCharCode(bytes[i]);\n  }\n  return btoa(binaryString);\n}\n\nexport function base64urlToUint8Array(base64url: string): InstanceType<typeof Uint8Array> {\n  const base64 = base64url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n  const padding = \"=\".repeat((4 - (base64.length % 4)) % 4);\n  return base64ToUint8Array(base64 + padding);\n}\n\nexport function uint8ArrayToBase64url(bytes: Uint8Array): string {\n  return uint8ArrayToBase64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\n}\n\nexport function hexToUint8Array(hex: string): InstanceType<typeof Uint8Array> {\n  const cleanHex = hex.replace(/^0x/, \"\");\n  if (cleanHex.length % 2 !== 0) {\n    throw new Error(\"Invalid hex string length\");\n  }\n  const bytes = new Uint8Array(cleanHex.length / 2);\n  for (let i = 0; i < cleanHex.length; i += 2) {\n    bytes[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);\n  }\n  return bytes;\n}\n\nexport function uint8ArrayToHex(bytes: Uint8Array): string {\n  return Array.from(bytes)\n    .map((b) => b.toString(16).padStart(2, \"0\"))\n    .join(\"\");\n}\n\n// instanceof\nexport abstract class Class {\n  constructor(..._args: any[]) {}\n}","sourceCodeStart":947,"sourceCodeEnd":983,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/core/util.ts#L947-L983","documentation":"Thrown by hexToUint8Array() when the input hex string has an odd number of characters (after stripping an optional `0x` prefix). Each byte is two hex digits, so an odd-length string cannot be split into complete byte pairs. Used by codec helpers that back the `hex`/base64 string formats and any caller converting hex to bytes.","triggerScenarios":"Passing a malformed hex value like `\"0x4A3\"`, `\"abc\"`, or a string that lost a leading zero (e.g. `\"0FF\"` instead of `\"00FF\"`). Also hit when user input or a DB column stores hex without zero-padding single-digit bytes.","commonSituations":"Storing hashes/IDs as hex without fixed-width padding; trimming leading zeros from a hash string; copy-paste truncation; user-supplied color codes, transaction IDs, or fingerprints with a missing digit.","solutions":["Pad the hex string to an even length with a leading zero: `hex.length % 2 ? '0' + hex : hex`.","Strip whitespace and any non-hex characters before conversion, then re-check length.","Validate the source format upstream (fixed-width hex columns, zero-padded input fields)."],"exampleFix":"// before\nutil.hexToUint8Array('0x4A3'); // throws: odd length\n\n// after\nconst clean = '0x4A3'.replace(/^0x/, '');\nconst padded = clean.length % 2 ? '0' + clean : clean;\nutil.hexToUint8Array(padded);","handlingStrategy":"validation","validationCode":"function toEvenHex(input: string): string {\n  const clean = input.trim().replace(/^0x/i, '');\n  if (!/^[0-9a-fA-F]*$/.test(clean)) {\n    throw new TypeError('Input is not a valid hex string');\n  }\n  return clean.length % 2 ? '0' + clean : clean;\n}\n// util.hexToUint8Array(toEvenHex(userHex));","typeGuard":"function isValidHex(input: string): boolean {\n  const clean = input.trim().replace(/^0x/i, '');\n  return /^[0-9a-fA-F]*$/.test(clean) && clean.length % 2 === 0 && clean.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Pad hex columns/fields to fixed even widths at the storage boundary.","Validate hex input (regex + even length) before passing to codec helpers.","Avoid trimming leading zeros from hash strings; store them with full width."],"tags":["codec","hex","validation","input-validation","zod-v4"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}