apache/cassandra · error · MarshalException
Unexpected extraneous bytes after + getCollectionName() + va
Error message
Unexpected extraneous bytes after + getCollectionName() + value
What it means
CollectionSerializer.unpack() deserializes a serialized collection (list/set/map) by reading count-prefixed elements. After reading all elements declared by the count, it verifies no leftover bytes remain in the input; if they do, the buffer is not a valid encoding of this collection type, so MarshalException is thrown.
Source
Thrown at src/java/org/apache/cassandra/serializers/CollectionSerializer.java:98
throw new MarshalException("The data cannot be deserialized as a " + getCollectionName());
// If the received bytes are not corresponding to a collection, the size might be a huge number.
// In such a case we do not want to initialize the list with that size as it can result
// in an OOM. On the other hand we do not want to have to resize the list
// if we can avoid it, so we put a reasonable limit on the initialCapacity.
List<V> values = new ArrayList<>(Math.min(elements, 256));
int offset = sizeOfCollectionSize();
for (int i = 0; i < elements; i++)
{
V value = readValue(input, accessor, offset);
offset += sizeOfValue(value, accessor);
values.add(value);
}
if (!accessor.isEmptyFromOffset(input, offset))
throw new MarshalException("Unexpected extraneous bytes after " + getCollectionName() + " value");
return values;
}
catch (BufferUnderflowException | IndexOutOfBoundsException e)
{
throw new MarshalException("Not enough bytes to read a " + getCollectionName());
}
}
/**
* Return the collection name for error messages.
* @return the collection name for error messages.
*/
private String getCollectionName()
{
return toLowerCaseLocalized(getType().getSimpleName());
}
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Verify the byte buffer is produced by CollectionSerializer.serialize and not concatenated with unrelated bytes
- Check for trailing bytes by confirming buffer length matches the encoded collection size
- Re-serialize the value with the current Cassandra version's serializer instead of reusing old bytes
- If reading from storage, run repair/scrub to detect corruption
Example fix
// before ByteBuffer bad = ByteBuffer.allocate(serialized.remaining() + extra.length); bad.put(serialized); bad.put(extra); // trailing bytes // after ByteBuffer good = CollectionSerializer.getInstance(...).serialize(value);
Defensive patterns
Strategy: validation
Validate before calling
public static void checkCollectionBytes(ByteBuffer buf) {
if (buf == null || buf.remaining() == 0) return;
ByteBuffer dup = buf.duplicate();
int count = dup.getInt();
long total = 4;
for (int i = 0; i < count; i++) {
int size = dup.getInt(); total += 4;
if (size >= 0) { total += size; dup.position(dup.position() + size); }
}
if (dup.hasRemaining()) throw new MarshalException("trailing bytes in collection value");
} Type guard
public static boolean isValidCollection(ByteBuffer buf) {
try { checkCollectionBytes(buf); return true; } catch (Exception e) { return false; }
} Try / catch
try {
List<ByteBuffer> values = serializer.deserialize(buffer);
} catch (MarshalException e) {
logger.warn("Malformed collection value: {}", e.getMessage());
// treat as absent value
} Prevention
- Always produce collection bytes via CollectionSerializer.serialize
- Never append unrelated bytes to a serialized collection buffer
- Validate buffers in tests before shipping serialization changes
When it happens
Trigger: Calling deserialize/validate (via unpack) on a byte buffer whose byte length exceeds the sum of the element count prefix plus all encoded elements — e.g. corrupted SSTable/mutation bytes, manually crafted byte buffers, or bytes written by an incompatible serializer version.
Common situations: Hand-building collection ByteBuffers for tests or UDFs with trailing garbage; upgrading across Cassandra versions where collection encoding changed; corruption from wrong serialization of nested collections.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Not enough bytes to read size of %dth field %s
- Not enough bytes to read %dth field %s
- Not enough bytes to read size of %dth component
- Not enough bytes to read %dth component
- Invalid 32-bits integer value, expecting 4 bytes but got %d
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/cc23f5cd797d0ab6.
Report an issue: GitHub.