{"record":{"id":"44c71e67a9a2baa5","repo":"apache/cassandra","slug":"expected-2-bytes-for-a-smallint-d","errorCode":null,"errorMessage":"Expected 2 bytes for a smallint (%d)","messagePattern":"Expected 2 bytes for a smallint \\((.+?)\\)","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/serializers/ShortSerializer.java","lineNumber":43,"sourceCode":"\npublic class ShortSerializer extends TypeSerializer<Short>\n{\n    public static final ShortSerializer instance = new ShortSerializer();\n\n    public <V> Short deserialize(V value, ValueAccessor<V> accessor)\n    {\n        return accessor.isEmpty(value) ? null : accessor.toShort(value);\n    }\n\n    public ByteBuffer serialize(Short value)\n    {\n        return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value.shortValue());\n    }\n\n    public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException\n    {\n        if (accessor.size(value) != 2)\n            throw new MarshalException(String.format(\"Expected 2 bytes for a smallint (%d)\", accessor.size(value)));\n    }\n\n    public String toString(Short value)\n    {\n        return value == null ? \"\" : String.valueOf(value);\n    }\n\n    public Class<Short> getType()\n    {\n        return Short.class;\n    }\n}\n","sourceCodeStart":25,"sourceCodeEnd":56,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/serializers/ShortSerializer.java#L25-L56","documentation":"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.","triggerScenarios":"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.","commonSituations":"Type confusion between tinyint/smallint/int/bigint columns; drivers sending raw buffers instead of typed values; application code allocating the wrong-sized buffer.","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."],"exampleFix":"// before\nstmt.setBytesUnsafe(Bytes.allocate(4).putInt(v).flip()); // int-sized\n// after\nstmt.setShort(\"col\", (short) v);","handlingStrategy":"validation","validationCode":"// Java\nif (value == null || value.remaining() != 2) {\n    throw new IllegalArgumentException(\"smallint needs exactly 2 bytes, got \" + (value == null ? 0 : value.remaining()));\n}","typeGuard":"boolean isSmallintBuffer(ByteBuffer b) { return b != null && b.remaining() == 2; }","tryCatchPattern":"try {\n    short s = ShortSerializer.instance.deserialize(buf.duplicate());\n} catch (MarshalException e) {\n    log.warn(\"Bad smallint: {}\", e.getMessage());\n}","preventionTips":["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"],"tags":["cassandra","serialization","smallint","validation"],"backgroundTag":"type-mismatch","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}