{"record":{"id":"fb2b9506a9442fe5","repo":"apache/cassandra","slug":"invalid-bytes-remaining-after-an-end-of-component","errorCode":null,"errorMessage":"Invalid bytes remaining after an end-of-component at component","messagePattern":"Invalid bytes remaining after an end-of-component at component","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java","lineNumber":328,"sourceCode":"            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\n    {\n        // no constraints defined for the partition keys\n        if (!constraints.hasRelevantConstraints())\n            return;\n\n        ValueAccessor<ByteBuffer> accessor = ByteBufferAccessor.instance;\n\n        boolean isStatic = readIsStatic(input, accessor);\n        int offset = startingOffset(isStatic);\n","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java#L310-L346","documentation":"Thrown by AbstractCompositeType when deserializing/validating a composite value: after reading a component's end-of-component byte (0), additional bytes were found before the next component starts. The serialized composite is malformed — components must be terminated by exactly one zero byte with no trailing garbage in that slice.","triggerScenarios":"Calling AbstractCompositeType (or a subclass like CompositeType) validate/compose on a ByteBuffer whose serialized bytes contain non-zero bytes immediately after an end-of-component marker (byte != 0 at offset after marker while bytes remain).","commonSituations":"Corrupted SSTable or mutation data; hand-built composite ByteBuffers with wrong offsets/lengths; bugs in tools or drivers writing composite values directly; partial reads truncating a value incorrectly.","solutions":["Regenerate the composite value using CompositeType.build() / the official serializer instead of hand-assembling bytes.","Check for data corruption: run scrub/verify on affected SSTables and restore from backup if needed.","Verify the client driver or tool writes composite values with correct length-prefixed components and a single terminating 0 byte."],"exampleFix":"// before: hand-built composite\nByteBuffer bad = ByteBuffer.allocate(bytes.length + 1);\nbad.put(bytes).put((byte) 0);\n// after\nByteBuffer good = CompositeType.getInstance(BytesType.instance)\n        .decompose(\"cell-name\");","handlingStrategy":"validation","validationCode":"ByteBuffer v = serialized;\n// round-trip check before use\ntry { compositeType.validate(v); } catch (MarshalException e) { /* rebuild with CompositeType.build() */ }","typeGuard":"boolean isValidComposite(ByteBuffer v) { try { compositeType.validate(v.duplicate()); return true; } catch (MarshalException e) { return false; } }","tryCatchPattern":"catch (MarshalException e) { log.error(\"corrupt composite value\", e); value = rebuildComposite(rawBytes); }","preventionTips":["Always build composites via CompositeType.build()/decompose, never raw byte assembly.","Validate any externally produced byte buffers before storing.","Run periodic scrub/verify to catch on-disk corruption early."],"tags":["serialization","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"}