apache/cassandra · error · MarshalException
Unexpected extraneous bytes after set value
Error message
Unexpected extraneous bytes after set value
What it means
SetSerializer.validate decodes the declared number of elements and then checks that no bytes remain after the last element. Leftover bytes mean the buffer is longer than the encoded set it claims to hold, so the value is rejected as malformed. This keeps corrupt or wrongly-sized data from entering the database.
Source
Thrown at src/java/org/apache/cassandra/serializers/SetSerializer.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 set");
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 set value");
}
catch (BufferUnderflowException | IndexOutOfBoundsException e)
{
throw new MarshalException("Not enough bytes to read a set");
}
}
@Override
public <V> Set<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 set");
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Re-serialize the set with SetSerializer.serialize instead of assembling bytes manually.
- Trim the buffer to the exact serialized length (duplicate + limit) before validating.
- Check the code path that produced the buffer for slicing/concatenation bugs.
- Catch MarshalException and treat the value as invalid/corrupt.
Example fix
// before ByteBuffer padded = ByteBuffer.allocate(serialized.remaining() + 8); padded.put(serialized); setSerializer.validate(padded, ByteBufferAccessor.instance); // after setSerializer.validate(serialized.duplicate(), ByteBufferAccessor.instance);
Defensive patterns
Strategy: validation
Validate before calling
// Java ByteBuffer dup = buf.duplicate(); setSerializer.validate(dup, ByteBufferAccessor.instance); // rejects trailing bytes
Try / catch
try {
setSerializer.validate(buf.duplicate(), ByteBufferAccessor.instance);
} catch (MarshalException e) {
log.warn("Set value malformed: {}", e.getMessage());
} Prevention
- Never concatenate or pad serialized collection buffers
- Slice buffers to exact serialized lengths
- Re-serialize collections instead of hand-assembling bytes
When it happens
Trigger: Validating a buffer with trailing garbage, concatenating two serialized sets, or passing bytes whose size prefix undercounts the real element count relative to buffer length (e.g. buffer padded or holding another value appended).
Common situations: Manual byte-buffer slicing off-by-one errors; application code appending extra bytes; corrupt storage payload surfaced during validation; test harnesses building buffers by hand.
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 a set
- The duration months, days and nanoseconds must be all of the
- The data cannot be deserialized as a set
- Expected 2 bytes for a smallint (%d)
- REVOKE operation is not supported by AllowAllAuthorizer
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/aa6b8fa24c9c0f36.
Report an issue: GitHub.