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

  1. Verify the byte buffer is produced by CollectionSerializer.serialize and not concatenated with unrelated bytes
  2. Check for trailing bytes by confirming buffer length matches the encoded collection size
  3. Re-serialize the value with the current Cassandra version's serializer instead of reusing old bytes
  4. 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

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


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