apache/cassandra · error · InvalidTypeException

Invalid 8-bits integer value, expecting 1 byte but got %d

Error message

Invalid 8-bits integer value, expecting 1 byte but got %d

What it means

Thrown by ByteCodec.deserializeNoBoxing when the ByteBuffer does not contain exactly 1 byte, the wire size of a CQL tinyint. Null/empty buffers return 0; any other length is invalid for an 8-bit signed integer.

Source

Thrown at src/java/org/apache/cassandra/cql3/functions/types/TypeCodec.java:1589

        {
            if (value == null) return "NULL";
            return Byte.toString(value);
        }

        @Override
        public ByteBuffer serializeNoBoxing(byte value, ProtocolVersion protocolVersion)
        {
            ByteBuffer bb = ByteBuffer.allocate(1);
            bb.put(0, value);
            return bb;
        }

        @Override
        public byte deserializeNoBoxing(ByteBuffer bytes, ProtocolVersion protocolVersion)
        {
            if (bytes == null || bytes.remaining() == 0) return 0;
            if (bytes.remaining() != 1)
                throw new InvalidTypeException(
                "Invalid 8-bits integer value, expecting 1 byte but got " + bytes.remaining());

            return bytes.get(bytes.position());
        }
    }

    /**
     * This codec maps a CQL {@link DataType#smallint()} to a Java {@link Short}.
     */
    private static class SmallIntCodec extends PrimitiveShortCodec
    {

        private static final SmallIntCodec instance = new SmallIntCodec();

        private SmallIntCodec()
        {
            super(smallint());
        }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Check the column's declared CQL type and use the matching codec (ShortCodec for smallint, IntCodec for int).
  2. Log bytes.remaining() to infer the actual encoded width (2/4/8) and switch codecs accordingly.
  3. Use the row-level typed getters (getByte/getShort/getInt) so type selection is automatic.
  4. Migrate data to the intended type if producers and consumers disagree.

Example fix

// before
byte b = new ByteCodec().deserializeNoBoxing(bytes, ProtocolVersion.V4);
// after
switch (bytes.remaining()) {
    case 1: return new ByteCodec().deserializeNoBoxing(bytes, ProtocolVersion.V4);
    case 2: return (byte) new ShortCodec().deserializeNoBoxing(bytes, ProtocolVersion.V4);
    case 4: return (byte) new IntCodec().deserializeNoBoxing(bytes, ProtocolVersion.V4);
    default: throw new IllegalArgumentException("Unexpected width " + bytes.remaining());
}
Defensive patterns

Strategy: validation

Validate before calling

if (bytes == null || bytes.remaining() == 0) return (byte) 0;
if (bytes.remaining() != 1)
    throw new IllegalArgumentException("Expected 1 byte for tinyint, got " + bytes.remaining());

Type guard

boolean isByteSized(ByteBuffer b) { return b != null && (b.remaining() == 0 || b.remaining() == 1); }

Try / catch

try { return codec.deserializeNoBoxing(bytes, protocolVersion); }
catch (InvalidTypeException e) {
    log.warn("Tinyint deserialization failed: {} bytes", bytes.remaining());
    return (byte) 0;
}

Prevention

When it happens

Trigger: Calling ByteCodec.deserializeNoBoxing(bytes, protocolVersion) with a ByteBuffer whose remaining() is 2, 4, 8, etc., typically deserializing a smallint/int/bigint column as tinyint.

Common situations: Column type changed from int to tinyint (or vice versa) in one environment but not another, manual UDT/collection element parsing with wrong codec, or importing legacy 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/f43c43588c9a0150. Report an issue: GitHub.