apache/dubbo · error · IllegalArgumentException
hex string format error [${c}].
Error message
hex string format error [${c}]. What it means
Thrown by the private hex(char) helper (Bytes.java:866) when a character is not a valid hex digit (outside '0'-'9', 'a'-'f', 'A'-'F'). It is reachable through the public Bytes.hex2bytes(String) and hex2bytes(String, int, int) methods: after those validate parity and bounds, they iterate the string and call hex() per character, so any non-hex char surfaces as IllegalArgumentException with the offending character in the message.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java:876
*
* @param is input stream.
* @return MD5 byte array.
*/
public static byte[] getMD5(InputStream is) throws IOException {
return getMD5(is, 1024 * 8);
}
private static byte hex(char c) {
if (c <= '9') {
return (byte) (c - '0');
}
if (c >= 'a' && c <= 'f') {
return (byte) (c - 'a' + 10);
}
if (c >= 'A' && c <= 'F') {
return (byte) (c - 'A' + 10);
}
throw new IllegalArgumentException("hex string format error [" + c + "].");
}
private static int indexOf(char[] cs, char c) {
for (int i = 0, len = cs.length; i < len; i++) {
if (cs[i] == c) {
return i;
}
}
return -1;
}
private static byte[] decodeTable(String code) {
int hash = code.hashCode();
byte[] ret = DECODE_TABLE_MAP.get(hash);
if (ret == null) {
if (code.length() < 64) {
throw new IllegalArgumentException("Base64 code length < 64.");
}View on GitHub (pinned to 3a3043227f)
Solutions
- Strip separators and prefixes before decoding: str = str.replaceAll("[^0-9A-Fa-f]", "").
- Remove a leading '0x' if present: if (str.startsWith("0x")) str = str.substring(2);
- Validate with a regex first so you control the error message: if (!str.matches("[0-9A-Fa-f]*")) ... (note hex2bytes also requires even length).
Example fix
// before
byte[] b = Bytes.hex2bytes("de:ad:be:ef"); // ':' is not a hex digit
// after
String clean = "de:ad:be:ef".replace(":", "");
byte[] b = Bytes.hex2bytes(clean); Defensive patterns
Strategy: validation
Validate before calling
String clean = str.replaceAll("[^0-9A-Fa-f]", "");
if (clean.length() % 2 != 0) throw new IllegalArgumentException("hex length must be even");
byte[] b = Bytes.hex2bytes(clean); Type guard
static boolean isHexString(String s) {
return s != null && s.matches("[0-9A-Fa-f]*") && s.length() % 2 == 0;
} Try / catch
try {
byte[] b = Bytes.hex2bytes(str);
} catch (IllegalArgumentException e) {
// non-hex char or odd length — reject the untrusted input
throw new IllegalArgumentException("invalid hex input", e);
} Prevention
- Strip separators (':', '-', ' ') and any '0x' prefix before hex2bytes.
- Validate hex with a regex before decoding to control the error.
- Ensure even character count — each byte is two hex digits.
When it happens
Trigger: Calling Bytes.hex2bytes("48656c6c6f") is fine; calling hex2bytes("48656c6c6g") (note 'g') or hex2bytes("de/ad") (contains '/') triggers it; also hex2bytes on input with whitespace, '0x' prefix, or wrong case region.
Common situations: Hex strings copied with a '0x' prefix or spaces/colons/dashes between bytes; uppercase/lowercase assumed but a non-hex char slipped in; a digest/UUID string with separators passed straight through; truncated nibble.
Related errors
- base642bytes: base64 string length % 4 == 1.
- base642bytes: base64 string length error.
- unterminated escape sequence at index ${i} of: ${str}
- hex2bytes: ( len & 1 ) == 1.
- bytes2base64: length < 0, length is {}
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/8701f4b03121d74e.
Report an issue: GitHub.