apache/cassandra · error · MarshalException
Not enough bytes to read a set
Error message
Not enough bytes to read a set
What it means
SetSerializer.validate rejects an empty (zero-byte) value because a valid serialized set must contain at least the collection-size prefix. Cassandra historically serializes empty collections as null; a zero-length buffer is therefore treated as malformed rather than as an empty set. This guard runs during validation of values being written or bound.
Source
Thrown at src/java/org/apache/cassandra/serializers/SetSerializer.java:74
this.elements = elements;
this.comparators = comparators;
}
@Override
public List<ByteBuffer> serializeValues(Set<T> values)
{
List<ByteBuffer> buffers = new ArrayList<>(values.size());
for (T value : values)
buffers.add(elements.serialize(value));
buffers.sort(comparators.buffer);
return buffers;
}
@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");
}
}View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Pass null instead of an empty buffer to unset/delete the set, or pass a properly encoded set of the elements you want.
- If the intent is to store an empty set, encode it with SetSerializer.serialize(Collections.emptySet()) (4-byte zero count) rather than a zero-length buffer.
- In test code, use the serializer's own serialize method to build valid inputs.
Example fix
// before
boundStatement.setBytes("tags", ByteBuffer.allocate(0));
// after
boundStatement.setToNull("tags"); // or
boundStatement.setSet("tags", Collections.emptySet(), String.class); Defensive patterns
Strategy: validation
Validate before calling
// Java
if (buf == null || buf.remaining() == 0) {
// treat as unset; bind null instead
} else {
setSerializer.validate(buf.duplicate(), ByteBufferAccessor.instance);
} Try / catch
try {
setSerializer.validate(buf, ByteBufferAccessor.instance);
} catch (MarshalException e) {
throw new IllegalArgumentException("Invalid set value: " + e.getMessage(), e);
} Prevention
- Represent unset/empty collections as null, not zero-length buffers
- Use setSerializer.serialize(Collections.emptySet()) for explicit empty sets
- Bind typed collections via driver APIs instead of raw bytes
When it happens
Trigger: Binding a zero-length ByteBuffer to a set column (e.g. ByteBufferUtil.EMPTY_BYTE_BUFFER) via execute/bound statements, or validating an empty buffer in a custom type test such as setSerDerTest.
Common situations: Client drivers or app code constructing an empty set value as an empty buffer instead of null; migrations that write empty collections; custom serialization tests feeding empty input.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Unexpected extraneous bytes after set value
- 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/e662b75b8379fcff.
Report an issue: GitHub.