apache/cassandra · error · MarshalException
Unexpected extraneous bytes after list value
Error message
Unexpected extraneous bytes after list value
What it means
After reading the declared number of list elements, ListSerializer.validate() checks that no bytes remain between the current offset and the end of the buffer. Leftover trailing bytes mean the buffer is longer than the encoded list it claims to contain, so the data is corrupt or mis-framed. This catches buffers that concatenate a list with unrelated extra data.
Source
Thrown at src/java/org/apache/cassandra/serializers/ListSerializer.java:86
@Override
public <V> void validate(V input, ValueAccessor<V> accessor)
{
if (accessor.isEmpty(input))
throw new MarshalException("Not enough bytes to read a list");
try
{
int n = readCollectionSize(input, accessor);
int offset = sizeOfCollectionSize();
for (int i = 0; i < n; i++)
{
V value = readNonNullValue(input, accessor, offset);
offset += sizeOfValue(value, accessor);
elements.validate(value, accessor);
}
if (!accessor.isEmptyFromOffset(input, offset))
throw new MarshalException("Unexpected extraneous bytes after list value");
}
catch (BufferUnderflowException | IndexOutOfBoundsException e)
{
throw new MarshalException("Not enough bytes to read a list");
}
}
@Override
public <V> List<T> deserialize(V input, ValueAccessor<V> accessor)
{
try
{
int n = readCollectionSize(input, accessor);
int offset = sizeOfCollectionSize();
if (n < 0)
throw new MarshalException("The data cannot be deserialized as a list");
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Regenerate the serialized list with the official ListSerializer instead of hand-built buffers.
- Inspect the source of the buffer (ETL job, migration tool) for extra padding or appended fields and strip them.
- Check for double-wrapping: a ByteBuffer serialized inside another collection framing.
- If data at rest is corrupt, run a repair/scrub to rewrite the affected rows.
Example fix
// before ByteBuffer bad = ByteBuffer.allocate(4 + 4).putInt(0).putInt(42); // count + trailing int // after List<Integer> l = Collections.singletonList(42); ByteBuffer good = ListSerializer.instance.serialize(l, Int32Type.instance, ByteBufferUtil.NONE); // use proper serializer
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate framing: expected bytes = 4 + sum(element sizes); if (blob.remaining() != expected) reject before validate()
Try / catch
try { listSerializer.validate(blob, ByteBufferUtil.NONE); } catch (org.apache.cassandra.exceptions.MarshalException e) { log.error("list blob misframed: {}", e.getMessage()); blob = reSerializeFromSource(); } Prevention
- Never hand-build collection buffers; use ListSerializer.serialize or driver codecs
- Strip padding/delimiters added by ETL pipelines before storing blobs
- Run scrub/repair if at-rest rows repeatedly fail validation
When it happens
Trigger: Calling ListSerializer.validate(input, accessor) where n elements read successfully but accessor.isEmptyFromOffset(input, offset) is false — i.e. extra bytes remain after the last element.
Common situations: Manual byte-concatenation of a list with a delimiter or padding; sending a frozen<list> blob that embeds extra fields; truncated/corrupt SSTable or hint data being re-validated; off-by-one errors in hand-rolled collection serialization.
Related errors
- Not enough bytes to read a list
- null is not supported inside collections
- Unexpected extraneous bytes after + getCollectionName() + va
- Null value read when not allowed
- The data cannot be deserialized as a list
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/0fefe7914482c745.
Report an issue: GitHub.