{"record":{"id":"b54101ef95149027","repo":"apache/cassandra","slug":"not-enough-bytes-to-read-value-of-component","errorCode":null,"errorMessage":"Not enough bytes to read value of component ","messagePattern":"Not enough bytes to read value of component ","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java","lineNumber":318,"sourceCode":"    public <V> void validate(V input, ValueAccessor<V> accessor)\n    {\n        boolean isStatic = readIsStatic(input, accessor);\n        int offset = startingOffset(isStatic);\n\n        int i = 0;\n        V previous = null;\n        while (!accessor.isEmptyFromOffset(input, offset))\n        {\n            AbstractType<?> comparator = validateComparator(i, input, accessor, offset);\n            offset += getComparatorSize(i, input, accessor, offset);\n\n            if (accessor.sizeFromOffset(input, offset) < 2)\n                throw new MarshalException(\"Not enough bytes to read value size of component \" + i);\n            int length = accessor.getUnsignedShort(input, offset);\n            offset += 2;\n\n            if (accessor.sizeFromOffset(input, offset) < length)\n                throw new MarshalException(\"Not enough bytes to read value of component \" + i);\n            V value = accessor.slice(input, offset, length);\n            offset += length;\n\n            comparator.validateCollectionMember(value, previous, accessor);\n\n            if (accessor.isEmptyFromOffset(input, offset))\n                throw new MarshalException(\"Not enough bytes to read the end-of-component byte of component\" + i);\n            byte b = accessor.getByte(input, offset++);\n            if (b != 0 && !accessor.isEmptyFromOffset(input, offset))\n                throw new MarshalException(\"Invalid bytes remaining after an end-of-component at component\" + i);\n\n            previous = value;\n            ++i;\n        }\n    }\n\n    @Override\n    public void checkConstraints(ByteBuffer input, ColumnConstraints constraints) throws ConstraintViolationException","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java#L300-L336","documentation":"During AbstractCompositeType.validate(), after reading a component's 2-byte size header the validator checks that `length` bytes are actually available. If fewer remain, MarshalException 'Not enough bytes to read value of component <i>' is thrown — the declared component length exceeds the remaining bytes, so the composite blob is truncated or the length header is wrong.","triggerScenarios":"Validating a serialized composite where a component advertises (via its unsigned-short length) more bytes than remain in the buffer — typical of hand-built composites with incorrect length fields or truncated byte arrays.","commonSituations":"Off-by-one or wrong-endian length writing in custom code building composite keys; truncation when copying values through string/UTF-8 conversions; import/export tools mangling binary values; corrupted stored values.","solutions":["Fix the serializer that writes the component length so it writes the exact value byte count as an unsigned short","Avoid round-tripping composite bytes through text encodings (Base64 or hex for transport instead)","Use the type's decompose()/build API rather than manual ByteBuffer assembly","Compare expected vs actual total byte length before submit: comparator sizes + sum(lengths+3)","Scrub/rebuild the table if stored sstable data is corrupt"],"exampleFix":"// before\nbb.putShort((short) value.length);\nbb.put(value, 0, value.length - 1); // wrong: one byte short\n// after\nbb.putShort((short) value.length);\nbb.put(value);","handlingStrategy":"validation","validationCode":"// check every component's declared length fits before calling the API\nint off = 0, i = 0;\nwhile (off < buf.remaining()) {\n    int hdr = /* comparator size */ 1;\n    int len = ((buf.get(off + hdr) & 0xff) << 8) | (buf.get(off + hdr + 1) & 0xff);\n    if (buf.remaining() < off + hdr + 2 + len)\n        throw new IllegalArgumentException(\"Component \" + i + \" length \" + len + \" exceeds remaining bytes\");\n    off += hdr + 2 + len + 1; ++i;\n}","typeGuard":null,"tryCatchPattern":"try {\n    type.validate(bytes);\n} catch (MarshalException e) {\n    if (e.getMessage().startsWith(\"Not enough bytes to read value of component\"))\n        logger.error(\"Composite length header corrupt — reserialize with decompose()\");\n    else throw e;\n}","preventionTips":["Write lengths with exactly the value byte count using ByteBuffer.putShort before put(value)","Skip length-field math entirely by using CompositeType.build/decompose","Hex-dump suspicious blobs and verify framing: header + 2-byte len + value + 0 terminator","Re-serialize values after any tooling that resizes or transforms them"],"tags":["serialization","composite-type","validation"],"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"}