apache/cassandra · error · MarshalException
Not enough bytes to read size of %dth field %s
Error message
Not enough bytes to read size of %dth field %s
What it means
When converting a serialized UserType (UDT) value to a CQL literal, CQL3Type.toCQLLiteral reads a 4-byte size prefix for each declared field. If fewer than 4 bytes remain where the next field's size should be, the buffer is corrupt/truncated and MarshalException is thrown naming the field index and name.
Source
Thrown at src/java/org/apache/cassandra/cql3/CQL3Type.java:406
@Override
public String toCQLLiteral(ByteBuffer buffer)
{
if (buffer == null)
return "null";
StringBuilder target = new StringBuilder();
buffer = buffer.duplicate();
target.append('{');
for (int i = 0; i < type.size(); i++)
{
// we allow the input to have less fields than declared so as to support field addition.
if (!buffer.hasRemaining())
break;
if (buffer.remaining() < 4)
throw new MarshalException(String.format("Not enough bytes to read size of %dth field %s", i, type.fieldName(i)));
int size = buffer.getInt();
if (i > 0)
target.append(", ");
target.append(ColumnIdentifier.maybeQuote(type.fieldNameAsString(i)));
target.append(": ");
// size < 0 means null value
if (size < 0)
{
target.append("null");
continue;
}
if (buffer.remaining() < size)
throw new MarshalException(String.format("Not enough bytes to read %dth field %s", i, type.fieldName(i)));View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Verify the ByteBuffer contains a complete, uncorrupted serialized UDT value (check remaining() against the expected encoding)
- Re-read or re-fetch the value — the stored data may be truncated
- Use TypeSerializer/UTCMetaData-compliant serialization paths instead of hand-building byte buffers
Example fix
// before String literal = udtType.asCQL3Type().toCQLLiteral(sliceOf(valueBuffer, 0, 6)); // truncated // after String literal = udtType.asCQL3Type().toCQLLiteral(valueBuffer.duplicate()); // full value
Defensive patterns
Strategy: try-catch
Validate before calling
if (buffer == null || buffer.remaining() < 4) throw new MarshalException("Buffer too small for UDT field"); Try / catch
try { String lit = udtType.asCQL3Type().toCQLLiteral(buffer); } catch (MarshalException e) { log.error("Corrupt UDT value: {}", e.getMessage(), e); } Prevention
- Only pass buffers produced by the official UserType serializer
- Check buffer.remaining() against expected field sizes before rendering
- Treat stored blobs as untrusted and wrap literal rendering in try-catch
When it happens
Trigger: Passing a truncated or manually corrupted ByteBuffer to toCQLLiteral for a UDT type; deserializing a value written by a different/broken serializer; off-by-one slicing of a serialized blob.
Common situations: Application code storing UDT blobs and re-rendering them after partial reads; data corruption on disk or in transit; protocol mismatches when bytes were hand-assembled.
Related errors
- Not enough bytes to read %dth field %s
- Not enough bytes to read size of %dth component
- Not enough bytes to read %dth component
- Invalid operation (%s) for non-UDT column %s
- Invalid operation (%s) for frozen UDT column %s
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/424177e1cd2f5eb7.
Report an issue: GitHub.