{"record":{"id":"5c1bbdaa965a3352","repo":"apache/cassandra","slug":"cannot-parse-s-as-hex-bytes-5c1bbd","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/CollectionType.java","lineNumber":135,"sourceCode":"    public ByteBuffer decompose(T value)\n    {\n        return super.decompose(value);\n    }\n\n    public <V> String getString(V value, ValueAccessor<V> accessor)\n    {\n        return BytesType.instance.getString(value, accessor);\n    }\n\n    public ByteBuffer fromString(String source)\n    {\n        try\n        {\n            return ByteBufferUtil.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    public boolean isCollection()\n    {\n        return true;\n    }\n\n    @Override\n    public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException\n    {\n        if (accessor.isEmpty(value))\n            throw new MarshalException(\"Not enough bytes to read a \" + toLowerCaseLocalized(kind.name()));\n        super.validate(value, accessor);\n    }\n\n    @Override\n    public <V> void validateCellValue(V cellValue, ValueAccessor<V> accessor) throws MarshalException","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/CollectionType.java#L117-L153","documentation":"CollectionType.fromString throws 'cannot parse ... as hex bytes' when the source string for a collection-typed value cannot be converted via ByteBufferUtil.hexToBytes. Collection literals are normally parsed by the grammar, but this path handles string→bytes conversion for collection inputs and fails on non-hex or odd-length input.","triggerScenarios":"Binding a non-hex string where the collection's key/value serializer expects hex bytes; programmatic Term construction for collection columns with malformed hex (e.g. 'zz' or odd-length 'abc'); corrupt string-encoded collection input routed through fromString.","commonSituations":"Custom drivers/tools building collection Terms from raw strings; replaying exported CQL where blob elements lost their hex encoding; frozen collections containing blobs hydrated from logs; JSON-style array strings pasted directly as collection input.","solutions":["Ensure the input is valid even-length hex before it reaches the collection parser","Hex-encode each element (bytesToHex per element) when constructing literals","Use proper CQL collection literal syntax ([1,2,3], {1:'a'}, {'k','v'}) instead of raw hex strings via fromString","For blob elements inside collections, encode each as valid hex"],"exampleFix":"// before\nTerm t = listType.fromString(\"abc\"); // odd-length hex\n// after\nTerm t = listType.fromString(\"0abc\"); // valid even-length hex","handlingStrategy":"validation","validationCode":"public static void assertCollectionHex(String s) {\n    if (s == null || s.isEmpty() || s.length() % 2 != 0 || !s.matches(\"[0-9a-fA-F]+\"))\n        throw new IllegalArgumentException(\"Invalid hex for collection: \" + s);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build collections via CQL literals or typed driver APIs, not raw hex strings","Hex-encode each element individually","Avoid replaying mangled exported CQL without validation","Prefer driver bound statements over hand-built Terms"],"tags":["cassandra","marshal","collection","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"}