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

  1. Confirm the cell's declared type in the schema matches the serializer used (list vs set vs map vs scalar).
  2. Repair/scrub the table if stored bytes are corrupted.
  3. If data came from a migration/loader, re-ingest with the correct schema.
  4. 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

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


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)