{"record":{"id":"27bb533cf5fd8660","repo":"apache/cassandra","slug":"not-enough-bytes-to-read-dth-s","errorCode":null,"errorMessage":"Not enough bytes to read %dth %s","messagePattern":"Not enough bytes to read (.+?)th (.+?)","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/TupleType.java","lineNumber":316,"sourceCode":"        return pack(accessor, Arrays.asList(componentBuffers));\n    }\n\n    @Override\n    public <V> List<V> unpack(V value, ValueAccessor<V> accessor)\n    {\n        int numberOfElements = size();\n        List<V> components = new ArrayList<>(numberOfElements);\n        int length = accessor.size(value);\n        int position = 0;\n        for (int i = 0; i < numberOfElements; i++)\n        {\n            if (position == length)\n            {\n                return components;\n            }\n\n            if (position + 4 > length)\n                throw new MarshalException(String.format(\"Not enough bytes to read %dth %s\", i, componentOrFieldName(i)));\n\n            int size = accessor.getInt(value, position);\n            position += 4;\n\n            // size < 0 means null value\n            if (size >= 0)\n            {\n                if (length - position < size)\n                    throw new MarshalException(String.format(\"Not enough bytes to read %dth %s\", i, componentOrFieldName(i)));\n\n                components.add(accessor.slice(value, position, size));\n                position += size;\n            }\n            else\n                components.add(null);\n        }\n\n        // error out if we got more values in the tuple/UDT than we expected","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/TupleType.java#L298-L334","documentation":"TupleType.unpack walks a serialized tuple value, reading a 4-byte length prefix before each component. If the buffer ends before a complete length prefix can be read, it throws this MarshalException identifying which component index could not be read — the serialized value is truncated or corrupt.","triggerScenarios":"Decomposing a ByteBuffer into tuple components (TupleType.elements/components/bufs/buildAndSplit) where the buffer is shorter than the serialized tuple — e.g. truncated storage, wrong byte offsets, or a hand-built buffer missing bytes.","commonSituations":"Manually concatenating component bytes without proper length prefixes; reading a column value with the wrong TupleType (fewer/shorter encoding); corrupted SSTable data or a slicing bug copying a partial buffer.","solutions":["Verify the buffer length and that the value was serialized by the same TupleType being used to unpack it.","Use the TupleType builder / valueType APIs instead of hand-assembling bytes.","Re-read the source data (or repair the table) if the underlying value is truncated; validate with type.validate() before unpacking."],"exampleFix":"// before\nByteBuffer tuple = ByteBuffer.wrap(new byte[]{0,0,0,5,'h','e','l','l'}); // truncated\nList<ByteBuffer> parts = tupleType.split(tuple);\n// after\nif (tuple.remaining() < expectedSize)\n    throw new IOException(\"truncated tuple value\");\nList<ByteBuffer> parts = tupleType.split(tuple);","handlingStrategy":"try-catch","validationCode":"if (value == null || value.remaining() < 4) throw new IllegalArgumentException(\"tuple value too short\");","typeGuard":null,"tryCatchPattern":"try { List<ByteBuffer> parts = tupleType.split(value); } catch (MarshalException e) { /* log corrupted value, e.getMessage(), skip/repair */ }","preventionTips":["Always build tuple values with TupleType builders, not manual byte assembly","Ensure the unpacking TupleType matches the one used at write time","Validate values with TupleType.validate() before unpacking; treat failures as data corruption and log for repair"],"tags":["cassandra","serialization","tuple","corrupt-data"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}