{"record":{"id":"50044c99f23ec489","repo":"apache/cassandra","slug":"non-hex-characters-in-str","errorCode":null,"errorMessage":"Non-hex characters in <str>","messagePattern":"Non-hex characters in <str>","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/functions/types/utils/Bytes.java","lineNumber":214,"sourceCode":"    /**\n     * Converts a CQL hex string representation into a byte array.\n     *\n     * <p>A CQL blob string representation consist of the hexadecimal representation of the blob\n     * bytes.\n     *\n     * @param str       the string converted in hex representation.\n     * @param strOffset he offset for starting the string conversion\n     * @return the byte array which the String was representing.\n     */\n    private static byte[] fromRawHexString(String str, int strOffset)\n    {\n        byte[] bytes = new byte[(str.length() - strOffset) / 2];\n        for (int i = 0; i < bytes.length; i++)\n        {\n            byte halfByte1 = charToByte[str.charAt(strOffset + i * 2)];\n            byte halfByte2 = charToByte[str.charAt(strOffset + i * 2 + 1)];\n            if (halfByte1 == -1 || halfByte2 == -1)\n                throw new IllegalArgumentException(\"Non-hex characters in \" + str);\n            bytes[i] = (byte) ((halfByte1 << 4) | halfByte2);\n        }\n        return bytes;\n    }\n}\n","sourceCodeStart":196,"sourceCodeEnd":220,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/functions/types/utils/Bytes.java#L196-L220","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nbyte[] b = Bytes.fromRawHexString(\"ab cd\"); // space is non-hex\n// after\nbyte[] b = Bytes.fromRawHexString(\"abcd\"); // strip whitespace first","handlingStrategy":"validation","validationCode":"String hex = raw.replaceAll(\"\\\\s\", \"\"); if (!hex.matches(\"[0-9a-fA-F]+\") || hex.length() % 2 != 0) throw new IllegalArgumentException(\"invalid hex: \" + raw);","typeGuard":null,"tryCatchPattern":"try { return Bytes.fromHexString(s); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Non-hex characters\")) throw new MalformedHexException(s, e); throw e; }","preventionTips":["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"],"tags":["blob","hex","validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}