apache/hadoop · error · RuntimeException
Not a hex character: {c}
Error message
Not a hex character: {c} What it means
Thrown by MD5Hash.charToNibble(char) when a character in the supposed hex string is not 0-9, a-f, or A-F. setDigest() walks the string two characters per byte; any stray character (g-z, symbols, whitespace, '0x' prefix) hits this RuntimeException. It means the input was never valid hex, independent of length — the length check in setDigest passed but the content check failed.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/MD5Hash.java:303
throw new IllegalArgumentException("Wrong length: " + hex.length());
byte[] digest = new byte[MD5_LEN];
for (int i = 0; i < MD5_LEN; i++) {
int j = i << 1;
digest[i] = (byte)(charToNibble(hex.charAt(j)) << 4 |
charToNibble(hex.charAt(j+1)));
}
this.digest = digest;
}
private static final int charToNibble(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'a' && c <= 'f') {
return 0xa + (c - 'a');
} else if (c >= 'A' && c <= 'F') {
return 0xA + (c - 'A');
} else {
throw new RuntimeException("Not a hex character: " + c);
}
}
}
View on GitHub (pinned to 2add963021)
Solutions
- Pre-validate with a regex (^[0-9a-fA-F]{32}$) and reject with a descriptive error naming the offending input.
- Strip non-hex noise before parsing: trim whitespace, remove a leading '0x', split off anything after whitespace.
- If the file is genuinely corrupted, regenerate the checksum instead of trying to parse it.
Example fix
// before: prefixed value blows up inside charToNibble
new MD5Hash("0x" + hex32);
// after: strict pre-validation with a useful error
if (!hex32.matches("[0-9a-fA-F]{32}")) {
throw new IllegalArgumentException("Not an MD5 hex string: '" + hex32 + "'");
}
new MD5Hash(hex32); Defensive patterns
Strategy: validation
Validate before calling
if (!hex.matches("[0-9a-fA-F]{32}")) {
throw new IllegalArgumentException(
"Invalid MD5 hex '" + hex + "' — must be exactly 32 hex chars");
}
md5.setDigest(hex); Type guard
static boolean isHexNibbleString(String s) {
return s != null && s.matches("[0-9a-fA-F]*") && (s.length() % 2) == 0;
} Prevention
- Normalize input before parsing: trim(), strip '0x' prefixes, remove surrounding quotes.
- Use a single regex guard ([0-9a-fA-F]{32}) to catch both this error and the length error at once.
- Regenerate corrupted checksum manifests rather than special-casing bad characters.
When it happens
Trigger: setDigest("0x" + hash) or a hash prefixed/suffixed with junk; a checksum line containing the filename because it wasn't split; whitespace or quotes embedded in the string; corrupted checksum files where a byte was replaced by a non-hex character.
Common situations: Parsing user-maintained checksum manifests; values read from properties files that still contain quoting; concatenation bugs that glue a path onto the hash; locale/case transformations that insert separators.
Related errors
- Wrong length: {digest.length}
- Wrong length: {hex.length}
- No schema options are provided
- No codec option is provided
- No good option for numDataUnits or numParityUnits found
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/5569704904e64eaf.
Report an issue: GitHub.