apache/cassandra · error · MarshalException
Not enough bytes to read a map
Error message
Not enough bytes to read a map
What it means
MapSerializer.validate first rejects an empty buffer with "Not enough bytes to read a map" because a serialized map must start with at least a 4-byte element count. This is thrown before any element parsing when input is empty. An empty map must still be serialized with a count of 0, not as zero bytes.
Solutions
- Write an empty map as a serialized map with count 0 (use the serializer's serialize(Maps.newHashMap()) rather than an empty buffer).
- Send an actual NULL (unset/null value) through CQL instead of an empty blob.
- Catch MarshalException and normalize empty input to an empty serialized map before validating.
- Check client driver version/usage so empty collections are encoded correctly.
Example fix
// before ByteBuffer bad = ByteBufferUtil.EMPTY_BYTE_BUFFER; // rejected // after Map<ByteBuffer, ByteBuffer> empty = new LinkedHashMap<>(); ByteBuffer ok = mapSerializer.serialize(empty); // 4-byte count == 0
Defensive patterns
Strategy: validation
Validate before calling
// Java
public static ByteBuffer serializeMapOrEmpty(MapType<?,?> mapType, Map<?,?> m) {
return (m == null || m.isEmpty())
? mapType.getSerializer().serialize(new LinkedHashMap<>()) // 4-byte zero count
: mapType.getSerializer().serialize(m);
} Type guard
boolean isNonEmptyMapBytes(ByteBuffer b) { return b != null && b.remaining() >= 4; } Try / catch
try { mapType.validate(value); } catch (MarshalException e) { /* normalize: empty buffer -> serialize empty map, else reject */ } Prevention
- Never encode empty collections as zero-length buffers; use count=0 serialization or CQL NULL.
- Always build collection values through the type's serializer.
- Add unit tests that validate every collection value your code produces.
When it happens
Trigger: Calling validate (directly or via MapType.validate / column validation on insert) with an empty or zero-length ByteBuffer for a map column.
Common situations: Client code writing an empty map as an empty buffer instead of a 0-count serialized map; blob literals of length 0 bound to map columns; uninitialized ByteBuffers in custom code.
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
- Unexpected extraneous bytes after map value
- Expected 1 byte for a tinyint
- Expected 1 or 0 byte value
- Expected 2 bytes for a smallint
- Invalid byte for ascii: + Byte.toString(b)
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/890952fc480cbb26.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/serializers/MapSerializer.java:97
return buffers;
}
public <E> int collectionSize(Collection<E> elements)
{
return elements.size() >> 1;
}
@Override
protected int numberOfSerializedElements(int collectionSize)
{
return collectionSize * 2; // keys and values
}
@Override
public <T> void validate(T input, ValueAccessor<T> accessor)
{
if (accessor.isEmpty(input))
throw new MarshalException("Not enough bytes to read a map");
try
{
int n = readCollectionSize(input, accessor);
int offset = sizeOfCollectionSize();
for (int i = 0; i < n; i++)
{
T key = readNonNullValue(input, accessor, offset);
offset += sizeOfValue(key, accessor);
keys.validate(key, accessor);
T value = readNonNullValue(input, accessor, offset);
offset += sizeOfValue(value, accessor);
values.validate(value, accessor);
}
if (!accessor.isEmptyFromOffset(input, offset))
throw new MarshalException("Unexpected extraneous bytes after map value");
}
catch (BufferUnderflowException | IndexOutOfBoundsException e)View on GitHub (pinned to 88fd0f6a0e)