apache/cassandra · error · MarshalException

Expected 4 or 0 byte int

Error message

Expected 4 or 0 byte int (%d)

What it means

Int32Serializer.validate() requires a serialized int to be exactly 4 bytes (or 0 bytes for empty). Any other length means the bytes cannot be a valid 32-bit integer, so a MarshalException is thrown. This prevents misinterpreting longer/shorter buffers as int values.

Solutions

  1. Serialize ints with the proper 4-byte encoding: ByteBuffer.allocate(4).putInt(value) or the Int32Type serializer.
  2. If values exceed int range or use 8 bytes, change the column type to bigint and use Long serialization.
  3. Check for accidental double-serialization (a ByteBuffer wrapped inside another ByteBuffer), which changes the length.
  4. Pre-write validation: assert buffer.remaining() == 4 || buffer.remaining() == 0.

Example fix

// before
ByteBuffer bytes = ByteBuffer.allocate(8).putLong(value); // column is int
// after
ByteBuffer bytes = ByteBuffer.allocate(4).putInt(value);
Defensive patterns

Strategy: validation

Validate before calling

if (buf != null && buf.remaining() != 4 && buf.remaining() != 0) throw new IllegalArgumentException("int needs exactly 4 bytes, got " + buf.remaining());

Type guard

boolean isValidInt32Bytes(java.nio.ByteBuffer b) { return b == null || b.remaining() == 0 || b.remaining() == 4; }

Try / catch

try { int32Type.validate(buf, accessor); } catch (org.apache.cassandra.exceptions.MarshalException e) { throw new IllegalArgumentException("bad int bytes: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Calling Int32Serializer.validate(value, accessor) (directly or via an Int32Type column) with a buffer whose size is neither 4 nor empty — e.g. an 8-byte long, varint-encoded bigint, or 1-byte tinyint written into an int column.

Common situations: Writing a Java long (8 bytes) into an int column; using thrift-era varint encoding; client code serializing Integer with a wrong-width buffer; migrations mapping bigint columns to int columns.

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/e2479eb4c44b6699. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/serializers/Int32Serializer.java:43

public class Int32Serializer extends TypeSerializer<Integer>
{
    public static final Int32Serializer instance = new Int32Serializer();

    public <V> Integer deserialize(V value, ValueAccessor<V> accessor)
    {
        return accessor.isEmpty(value) ? null : accessor.toInt(value);
    }

    public ByteBuffer serialize(Integer value)
    {
        return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
    }

    public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException
    {
        if (accessor.size(value) != 4 && !accessor.isEmpty(value))
            throw new MarshalException(String.format("Expected 4 or 0 byte int (%d)", accessor.size(value)));
    }

    public String toString(Integer value)
    {
        return value == null ? "" : String.valueOf(value);
    }

    public Class<Integer> getType()
    {
        return Integer.class;
    }
}

View on GitHub (pinned to 88fd0f6a0e)