{"record":{"id":"9fe6b9df5e1274b9","repo":"apache/cassandra","slug":"not-enough-bytes-to-header-of-the-comparator-part","errorCode":null,"errorMessage":"Not enough bytes to header of the comparator part of component %s","messagePattern":"Not enough bytes to header of the comparator part of component (.+?)","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java","lineNumber":486,"sourceCode":"            offset += bytesToCopy;\n\n            // Write the end-of-component byte.\n            accessor.putByte(result, offset, i != numComponents - 1 ? (byte) 0 : lastEoc);\n            offset += 1;\n        }\n        return result;\n    }\n\n    protected ParsedComparator parseComparator(int i, String part)\n    {\n        return new DynamicParsedComparator(part);\n    }\n\n    protected <V> AbstractType<?> validateComparator(int i, V input, ValueAccessor<V> accessor, int offset) throws MarshalException\n    {\n        AbstractType<?> comparator = null;\n        if (accessor.sizeFromOffset(input, offset) < 2)\n            throw new MarshalException(\"Not enough bytes to header of the comparator part of component \" + i);\n        int header = accessor.getShort(input, offset);\n        offset += TypeSizes.SHORT_SIZE;\n        if ((header & 0x8000) == 0)\n        {\n            if (accessor.sizeFromOffset(input, offset) < header)\n                throw new MarshalException(\"Not enough bytes to read comparator name of component \" + i);\n\n            V value = accessor.slice(input, offset, header);\n            String valueStr = null;\n            try\n            {\n                valueStr = accessor.toString(value);\n                comparator = TypeParser.parse(valueStr);\n            }\n            catch (CharacterCodingException ce)\n            {\n                // ByteBufferUtil.string failed.\n                // Log it here and we'll further throw an exception below since comparator == null","sourceCodeStart":468,"sourceCodeEnd":504,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java#L468-L504","documentation":"DynamicCompositeType.validateComparator() decodes each component of a dynamic composite value: the first 2 bytes are a header short that encodes either a byte length of a comparator class name or an alias bit. If fewer than 2 bytes remain at the current offset, the buffer is truncated/corrupt and this MarshalException is thrown during validation. It indicates malformed serialized composite data rather than a user-facing value problem.","triggerScenarios":"Reading or validating a DynamicCompositeType value whose byte buffer ends mid-component header, e.g. from a corrupt SSTable, a truncated mutation, or hand-built byte buffers written without the 2-byte header.","commonSituations":"Manual construction of composite ByteBuffers that omit the comparator header; data migrated between versions with different composite encodings; corruption or truncation during manual compaction/repair tooling.","solutions":["Verify the source of the byte buffer: re-read the value from the replica or take a fresh read path instead of the truncated buffer","If building composites by hand, use DynamicCompositeType.decompose(Object...) or buildDynamicComparator so headers are written correctly","Run repairs/scrub on the affected range if SSTable corruption is suspected","Check client/tool byte offsets: every component must start with a 2-byte header short"],"exampleFix":"// before\nByteBuffer bad = handBuiltWithoutHeader(\"abc\"); // missing 2-byte header\n// after\nByteBuffer ok = DynamicCompositeType.getInstance(aliases).decompose(\"abc\");","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { type.validate(buffer); } catch (MarshalException e) { quarantineCorruptRecord(buffer); }","preventionTips":["Never hand-build DynamicCompositeType buffers; use decompose()/build APIs","Include the 2-byte header short for every component","Treat MarshalException during reads as possible SSTable corruption and trigger repair/scrub"],"tags":["cassandra","composite-type","data-corruption"],"backgroundTag":"schema-validation-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}