apache/cassandra · error · MarshalException
Expected 2 bytes for a smallint (%d)
Error message
Expected 2 bytes for a smallint (%d)
What it means
ShortSerializer.validate enforces that a smallint value occupies exactly 2 bytes. A buffer of any other length cannot be decoded as a 16-bit signed integer, so validation fails with a message including the actual byte count. This runs when binding values or validating data before it is stored.
Source
Thrown at src/java/org/apache/cassandra/serializers/ShortSerializer.java:43
public class ShortSerializer extends TypeSerializer<Short>
{
public static final ShortSerializer instance = new ShortSerializer();
public <V> Short deserialize(V value, ValueAccessor<V> accessor)
{
return accessor.isEmpty(value) ? null : accessor.toShort(value);
}
public ByteBuffer serialize(Short value)
{
return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value.shortValue());
}
public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException
{
if (accessor.size(value) != 2)
throw new MarshalException(String.format("Expected 2 bytes for a smallint (%d)", accessor.size(value)));
}
public String toString(Short value)
{
return value == null ? "" : String.valueOf(value);
}
public Class<Short> getType()
{
return Short.class;
}
}
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Bind a Java Short/short instead of a raw ByteBuffer so the driver serializes it correctly.
- If supplying bytes, encode exactly 2 bytes via ShortSerializer.serialize or ByteBufferUtil.bytes(shortValue).
- Check the column type in the schema matches the intended numeric type (CAST if needed).
- In tests, validate the buffer length is 2 before calling the serializer.
Example fix
// before
stmt.setBytesUnsafe(Bytes.allocate(4).putInt(v).flip()); // int-sized
// after
stmt.setShort("col", (short) v); Defensive patterns
Strategy: validation
Validate before calling
// Java
if (value == null || value.remaining() != 2) {
throw new IllegalArgumentException("smallint needs exactly 2 bytes, got " + (value == null ? 0 : value.remaining()));
} Type guard
boolean isSmallintBuffer(ByteBuffer b) { return b != null && b.remaining() == 2; } Try / catch
try {
short s = ShortSerializer.instance.deserialize(buf.duplicate());
} catch (MarshalException e) {
log.warn("Bad smallint: {}", e.getMessage());
} Prevention
- Bind short/Short via driver typed setters instead of raw ByteBuffers
- Double-check column types: tinyint=1, smallint=2, int=4, bigint=8 bytes
- Use ShortSerializer.serialize() to produce buffers
When it happens
Trigger: Binding a ByteBuffer whose remaining() is 0, 1, 4 (int), or 8 (long/bigint) bytes to a smallint column; passing a value serialized as another numeric type; supplying raw bytes in a test.
Common situations: Type confusion between tinyint/smallint/int/bigint columns; drivers sending raw buffers instead of typed values; application code allocating the wrong-sized buffer.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- The duration months, days and nanoseconds must be all of the
- Not enough bytes to read a set
- Unexpected extraneous bytes after set value
- REVOKE operation is not supported by AllowAllAuthorizer
- %s is not a valid data resource name
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/44c71e67a9a2baa5.
Report an issue: GitHub.