{"record":{"id":"f5413dcf0383f355","repo":"chinabugotech/hutool","slug":"illegal-hexadecimal-character-at-index","errorCode":null,"errorMessage":"Illegal hexadecimal character {} at index {}","messagePattern":"Illegal hexadecimal character (.+?) at index (.+?)","errorType":"exception","errorClass":"UtilException","httpStatus":null,"severity":"error","filePath":"hutool-core/src/main/java/cn/hutool/core/codec/Base16Codec.java","lineNumber":114,"sourceCode":"\tpublic void appendHex(StringBuilder builder, byte b) {\n\t\tint high = (b & 0xf0) >>> 4;//高位\n\t\tint low = b & 0x0f;//低位\n\t\tbuilder.append(alphabets[high]);\n\t\tbuilder.append(alphabets[low]);\n\t}\n\n\t/**\n\t * 将十六进制字符转换成一个整数\n\t *\n\t * @param ch    十六进制char\n\t * @param index 十六进制字符在字符数组中的位置\n\t * @return 一个整数\n\t * @throws UtilException 当ch不是一个合法的十六进制字符时，抛出运行时异常\n\t */\n\tprivate static int toDigit(char ch, int index) {\n\t\tint digit = Character.digit(ch, 16);\n\t\tif (digit < 0) {\n\t\t\tthrow new UtilException(\"Illegal hexadecimal character {} at index {}\", ch, index);\n\t\t}\n\t\treturn digit;\n\t}\n}\n","sourceCodeStart":96,"sourceCodeEnd":119,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/codec/Base16Codec.java#L96-L119","documentation":"Base16Codec.toDigit converts a single hex char to its integer value via Character.digit(ch, 16); when the char is not a valid hex digit (0-9, a-f, A-F) the result is -1 and a UtilException (a RuntimeException) is thrown naming the offending char and its index. This occurs during hex decoding.","triggerScenarios":"Decoding a string containing non-hex characters (g-z, punctuation, whitespace) via HexUtil.decodeHex or Base16.decode. An odd-length input or characters outside [0-9a-fA-F].","commonSituations":"Parsing user input or file content assumed to be hex; concatenating hex strings with separators (0x prefix, colons) not stripped; encoding/decoding mismatch (treating base64 as hex).","solutions":["Sanitise input: strip 0x prefixes, whitespace, colons and uppercase/lowercase to a-f before decoding.","Validate with a regex (^[0-9a-fA-F]+$) and even length before calling decode.","Use HexUtil.decodeHexStr/decodeHex with a try-catch to report the bad input to the user."],"exampleFix":"// before\nbyte[] b = HexUtil.decodeHex(\"0x1F:2A\");\n// after\nString clean = input.replaceAll(\"0x|:|\\\\s\", \"\");\nif (!clean.matches(\"^[0-9a-fA-F]+$\") || clean.length()%2!=0) throw new IllegalArgumentException(\"bad hex\");\nbyte[] b = HexUtil.decodeHex(clean);","handlingStrategy":"validation","validationCode":"String clean = input.replaceAll(\"0x|:|\\\\s\", \"\");\nif (!clean.matches(\"^[0-9a-fA-F]+$\") || clean.length()%2!=0) throw new IllegalArgumentException(\"invalid hex: \" + input);","typeGuard":"static boolean isHex(String s) { return s != null && s.matches(\"^[0-9a-fA-F]+$\") && s.length()%2==0; }","tryCatchPattern":"try { return HexUtil.decodeHex(s); } catch (UtilException e) { throw new IllegalArgumentException(\"bad hex input\", e); }","preventionTips":["Strip prefixes/separators and validate hex alphabet before decoding.","Confirm even length."],"tags":["codec","hex","decoder","argument-validation"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}