apache/cassandra · error · IllegalArgumentException
Non-hex characters in <str>
Error message
Non-hex characters in <str>
What it means
Bytes.fromRawHexString converts a hex character pair stream into bytes using a lookup table where non-hex characters map to -1. If either nibble of any pair is -1, this IllegalArgumentException naming the whole offending string is thrown. It is the low-level validator behind fromHexString's content check.
Source
Thrown at src/java/org/apache/cassandra/cql3/functions/types/utils/Bytes.java:214
/**
* Converts a CQL hex string representation into a byte array.
*
* <p>A CQL blob string representation consist of the hexadecimal representation of the blob
* bytes.
*
* @param str the string converted in hex representation.
* @param strOffset he offset for starting the string conversion
* @return the byte array which the String was representing.
*/
private static byte[] fromRawHexString(String str, int strOffset)
{
byte[] bytes = new byte[(str.length() - strOffset) / 2];
for (int i = 0; i < bytes.length; i++)
{
byte halfByte1 = charToByte[str.charAt(strOffset + i * 2)];
byte halfByte2 = charToByte[str.charAt(strOffset + i * 2 + 1)];
if (halfByte1 == -1 || halfByte2 == -1)
throw new IllegalArgumentException("Non-hex characters in " + str);
bytes[i] = (byte) ((halfByte1 << 4) | halfByte2);
}
return bytes;
}
}
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Strip all whitespace and the 0x prefix, then verify the string matches ^[0-9a-fA-F]+$ before conversion.
- Sanitize the input (remove spaces/underscores/separators commonly added for readability).
- Use fromHexString (which skips the 2-char prefix) instead of calling fromRawHexString with a prefixed string.
- Locate the bad character by scanning with Character.digit(c, 16) == -1 and report its index upstream.
Example fix
// before
byte[] b = Bytes.fromRawHexString("ab cd"); // space is non-hex
// after
byte[] b = Bytes.fromRawHexString("abcd"); // strip whitespace first Defensive patterns
Strategy: validation
Validate before calling
String hex = raw.replaceAll("\\s", ""); if (!hex.matches("[0-9a-fA-F]+") || hex.length() % 2 != 0) throw new IllegalArgumentException("invalid hex: " + raw); Try / catch
try { return Bytes.fromHexString(s); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Non-hex characters")) throw new MalformedHexException(s, e); throw e; } Prevention
- Sanitize hex input: remove whitespace and 0x prefix before raw conversion
- Validate with regex before calling the Bytes utils
- When rendering hex for later parsing, never insert separators
When it happens
Trigger: fromHexString("0xzz12"), whitespace inside the hex like "0xab cd" (space is not hex), a '0x' prefix accidentally passed to fromRawHexString (which starts at index 0), Unicode look-alike characters pasted from docs.
Common situations: Copy-paste from formatted logs with spaces or line breaks inside hex; manual transcription errors; calling fromRawHexString directly with a prefixed string so 'x' becomes a non-hex character.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- A CQL blob string must have an even length (since one byte i
- A CQL blob string must start with "0x"
- cannot parse '%s' as hex bytes
- Token " + token + " contains non-hex digits
- REVOKE operation is not supported by AllowAllAuthorizer
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/50044c99f23ec489.
Report an issue: GitHub.