{"record":{"id":"09f8e8f8024a35ee","repo":"apache/cassandra","slug":"cannot-parse-s-as-hex-bytes","errorCode":null,"errorMessage":"cannot parse '%s' as hex bytes","messagePattern":"cannot parse '(.+?)' as hex bytes","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/BytesType.java","lineNumber":55,"sourceCode":"    private static final ByteBuffer MASKED_VALUE = ByteBufferUtil.EMPTY_BYTE_BUFFER;\n\n    BytesType() {super(ComparisonType.BYTE_ORDER);} // singleton\n\n    @Override\n    public boolean allowsEmpty()\n    {\n        return true;\n    }\n\n    public ByteBuffer fromString(String source)\n    {\n        try\n        {\n            return ByteBuffer.wrap(Hex.hexToBytes(source));\n        }\n        catch (NumberFormatException e)\n        {\n            throw new MarshalException(String.format(\"cannot parse '%s' as hex bytes\", source), e);\n        }\n    }\n\n    @Override\n    public Term fromJSONObject(Object parsed) throws MarshalException\n    {\n        try\n        {\n            String parsedString = (String) parsed;\n            if (!parsedString.startsWith(\"0x\"))\n                throw new MarshalException(String.format(\"String representation of blob is missing 0x prefix: %s\", parsedString));\n\n            return new Constants.Value(BytesType.instance.fromString(parsedString.substring(2)));\n        }\n        catch (ClassCastException | MarshalException exc)\n        {\n            throw new MarshalException(String.format(\"Value '%s' is not a valid blob representation: %s\", parsed, exc.getMessage()));\n        }","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/BytesType.java#L37-L73","documentation":"BytesType.fromString throws this when the source string cannot be converted from hex to bytes by Hex.hexToBytes. Blob values in CQL are hex strings; any non-hex character, odd-length string, or empty string causes NumberFormatException wrapped in this MarshalException.","triggerScenarios":"INSERT of blob literal 0xzz12 or odd-length hex like 'abc'; passing raw binary/text that was never hex-encoded; fromString called directly with a still-0x-prefixed string containing non-hex chars (e.g. the 'x').","commonSituations":"Hand-assembling blob literals in cqlsh; hex encoders producing prefixed strings passed unstripped to fromString; base64 data pasted where hex is required; log-replay of CQL statements with mangled blobs.","solutions":["Provide valid even-length hex characters (0-9, a-f), e.g. 0x68656c6c6f","Hex-encode the data properly: bytesToHex(byte[]) before insert","If data is base64, decode it first then re-encode as hex","Handle the 0x prefix exactly once — do not pass '0x' inside fromString if upstream already stripped it"],"exampleFix":"// before\nINSERT INTO t (k, b) VALUES (1, 0xzz12);\n// after\nINSERT INTO t (k, b) VALUES (1, 0xdeadbeef);","handlingStrategy":"validation","validationCode":"public static void assertHex(String s) {\n    String h = s.startsWith(\"0x\") ? s.substring(2) : s;\n    if (h.isEmpty() || h.length() % 2 != 0 || !h.matches(\"[0-9a-fA-F]+\"))\n        throw new IllegalArgumentException(\"Invalid hex: \" + s);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always hex-encode binary data before building CQL literals","Never base64-encode into blob columns","Beware double-stripping/adding the 0x prefix","Round-trip test encode→decode in CI for blob literals"],"tags":["cassandra","marshal","blob","hex"],"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"}