apache/cassandra · error · MarshalException

Not enough bytes to read %dth

Error message

Not enough bytes to read %dth %s

What it means

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.

Solutions

  1. Verify the buffer length and that the value was serialized by the same TupleType being used to unpack it.
  2. Use the TupleType builder / valueType APIs instead of hand-assembling bytes.
  3. Re-read the source data (or repair the table) if the underlying value is truncated; validate with type.validate() before unpacking.

Example fix

// before
ByteBuffer tuple = ByteBuffer.wrap(new byte[]{0,0,0,5,'h','e','l','l'}); // truncated
List<ByteBuffer> parts = tupleType.split(tuple);
// after
if (tuple.remaining() < expectedSize)
    throw new IOException("truncated tuple value");
List<ByteBuffer> parts = tupleType.split(tuple);
Defensive patterns

Strategy: try-catch

Validate before calling

if (value == null || value.remaining() < 4) throw new IllegalArgumentException("tuple value too short");

Try / catch

try { List<ByteBuffer> parts = tupleType.split(value); } catch (MarshalException e) { /* log corrupted value, e.getMessage(), skip/repair */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/27bb533cf5fd8660. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/marshal/TupleType.java:316

        return pack(accessor, Arrays.asList(componentBuffers));
    }

    @Override
    public <V> List<V> unpack(V value, ValueAccessor<V> accessor)
    {
        int numberOfElements = size();
        List<V> components = new ArrayList<>(numberOfElements);
        int length = accessor.size(value);
        int position = 0;
        for (int i = 0; i < numberOfElements; i++)
        {
            if (position == length)
            {
                return components;
            }

            if (position + 4 > length)
                throw new MarshalException(String.format("Not enough bytes to read %dth %s", i, componentOrFieldName(i)));

            int size = accessor.getInt(value, position);
            position += 4;

            // size < 0 means null value
            if (size >= 0)
            {
                if (length - position < size)
                    throw new MarshalException(String.format("Not enough bytes to read %dth %s", i, componentOrFieldName(i)));

                components.add(accessor.slice(value, position, size));
                position += size;
            }
            else
                components.add(null);
        }

        // error out if we got more values in the tuple/UDT than we expected

View on GitHub (pinned to 88fd0f6a0e)