apache/cassandra · error · MarshalException
The data cannot be deserialized as a + getCollectionName()
Error message
The data cannot be deserialized as a + getCollectionName()
What it means
CollectionSerializer.unpack reads the collection's element-count header and throws MarshalException("The data cannot be deserialized as a <collection>") when the count is negative, meaning the bytes are not a valid serialized collection of this type. This guards against garbage or wrongly-typed values whose first bytes decode to a bogus (often huge/negative) size.
Solutions
- Confirm the cell's declared type in the schema matches the serializer used (list vs set vs map vs scalar).
- Repair/scrub the table if stored bytes are corrupted.
- If data came from a migration/loader, re-ingest with the correct schema.
- Catch MarshalException at read sites and log hex of the value for diagnosis instead of crashing.
Example fix
// before
List<ByteBuffer> vals = listType.unpack(value, ByteBufferAccessor.instance); // MarshalException on wrong type
// after
try {
vals = listType.unpack(value, ByteBufferAccessor.instance);
} catch (MarshalException e) {
logger.warn("Value is not a valid list: {}", ByteBufferUtil.bytesToHex(value));
} Defensive patterns
Strategy: validation
Validate before calling
if (value == null || value.remaining() < 4) return false; // cannot be a serialized collection int n = value.getInt(value.position()); // header must be a sane non-negative count
Type guard
static boolean looksLikeCollection(ByteBuffer v) { return v != null && v.remaining() >= 4 && v.getInt(v.position()) >= 0; } Try / catch
try { list = collectionType.deserialize(value); } catch (MarshalException e) { logger.warn("Not a valid collection: {}", ByteBufferUtil.bytesToHex(value), e); } Prevention
- Never reinterpret cells with a different type than declared in the schema
- Keep loader/migration schemas in sync with the target table
- Treat MarshalException on reads as a data-corruption signal and run repair
- Avoid manual construction of collection serialized bytes
When it happens
Trigger: Calling unpack (directly or via deserialize) on a buffer that is not a serialized list/set/map of the expected type — e.g. a scalar value parsed as a collection, bytes written by a different Cassandra version or serializer, or corrupted cell data (src/java/org/apache/cassandra/serializers/CollectionSerializer.java:80).
Common situations: Schema mismatch: column altered between list/set/map or between collection and scalar; data loaded via sstableloader with wrong schema; corrupted SSTable bytes; custom code reinterpreting stored values.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Not enough bytes to read a + name
- Not enough bytes to read a
- cannot parse ' ' as hex bytes
- Invalid + charset + bytes + accessor.toHex(value)
- Not enough bytes to read %dth
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/02a63852e10e7eb0.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/serializers/CollectionSerializer.java:80
for (V value : values)
{
writeValue(result, value, accessor);
}
return accessor.valueOf((ByteBuffer) result.flip());
}
public List<ByteBuffer> unpack(ByteBuffer input)
{
return unpack(input, ByteBufferAccessor.instance);
}
public <V> List<V> unpack(V input, ValueAccessor<V> accessor)
{
try
{
int elements = numberOfSerializedElements(readCollectionSize(input, accessor));
if (elements < 0)
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");View on GitHub (pinned to 88fd0f6a0e)