apache/cassandra · error · MarshalException

Expected 1 byte for a tinyint (%d)

Error message

Expected 1 byte for a tinyint (%d)

What it means

ByteSerializer.validate requires a tinyint column's serialized value to be exactly 1 byte; MarshalException("Expected 1 byte for a tinyint (%d)") is thrown for any other length. The stored/written bytes do not match the tinyint wire format.

Source

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

public class ByteSerializer extends TypeSerializer<Byte>
{
    public static final ByteSerializer instance = new ByteSerializer();

    public <V> Byte deserialize(V value, ValueAccessor<V> accessor)
    {
        return value == null || accessor.isEmpty(value) ? null : accessor.toByte(value);
    }

    public ByteBuffer serialize(Byte 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) != 1)
            throw new MarshalException(String.format("Expected 1 byte for a tinyint (%d)", accessor.size(value)));
    }

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

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

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Use driver typed setters (setByte/setInt on a tinyint bound statement) so the value encodes as exactly 1 byte.
  2. Fix the ingestion pipeline to convert numeric types to byte before writing.
  3. Alter the column to the type actually being stored (e.g. int) if data is wider: ALTER TABLE t ALTER c TYPE int; (check compatibility).
  4. Rewrite corrupt/mismatched partitions with correctly typed values.

Example fix

// before
stmt.setInt("v", 42); // if driver encodes as 4 bytes into tinyint column
// after
stmt.setByte("v", (byte) 42); // exactly 1 byte
Defensive patterns

Strategy: type-guard

Validate before calling

if (buf != null && buf.remaining() != 1) throw new IllegalArgumentException("tinyint must be exactly 1 byte");

Type guard

static boolean isValidTinyint(ByteBuffer v) { return v == null || v.remaining() == 1; }

Try / catch

try { writeTinyint(stmt, num); } catch (InvalidQueryException e) { /* wrong width encoding for tinyint */ }

Prevention

When it happens

Trigger: Writing a short/int/long or text value into a tinyint column with a tool that doesn't apply type encoding; reading a cell typed tinyint that was written as another type; custom byte buffers handed to the serializer (src/java/org/apache/cassandra/serializers/ByteSerializer.java:43).

Common situations: External loaders (spark-connector misconfig, sstableloader with wrong schema) writing ints into tinyint columns; hand-built ByteBuffers of the wrong size; schema changed under existing data.

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


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