apache/kafka · critical · InvalidRecordException

Invalid value size found for control record key. Must have a

Error message

Invalid value size found for control record key. Must have at least {} bytes, but found only {}

What it means

ControlRecordType.parseTypeId(ByteBuffer) (line 90) requires at least 4 bytes (2-byte version + 2-byte type) per the fixed control-record key schema. A key shorter than 4 bytes cannot be interpreted and is rejected as InvalidRecordException, indicating the record batch is malformed, truncated, or corrupt.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/record/internal/ControlRecordType.java:90

        return type;
    }

    public ByteBuffer recordKey() {
        if (this == UNKNOWN)
            throw new IllegalArgumentException("Cannot serialize UNKNOWN control record type");
        return buffer.duplicate();
    }

    public int controlRecordKeySize() {
        return buffer.remaining();
    }

    public static short parseTypeId(ByteBuffer key) {
        // We should duplicate the original buffer since it will be read again in some cases, for example,
        // read by KafkaRaftClient and RaftClient.Listener
        ByteBuffer buffer = key.duplicate();
        if (buffer.remaining() < CONTROL_RECORD_KEY_SIZE)
            throw new InvalidRecordException("Invalid value size found for control record key. " +
                    "Must have at least " + CONTROL_RECORD_KEY_SIZE + " bytes, but found only " + buffer.remaining());

        short version = buffer.getShort();
        if (version < ControlRecordTypeSchema.LOWEST_SUPPORTED_VERSION)
            throw new InvalidRecordException("Invalid version found for control record: " + version +
                    ". May indicate data corruption");

        if (version > ControlRecordTypeSchema.HIGHEST_SUPPORTED_VERSION) {
            log.debug("Received unknown control record key version {}. Parsing as version {}", version,
                    ControlRecordTypeSchema.HIGHEST_SUPPORTED_VERSION);
            version = ControlRecordTypeSchema.HIGHEST_SUPPORTED_VERSION;
        }
        ControlRecordTypeSchema schema = new ControlRecordTypeSchema(new ByteBufferAccessor(buffer), version);
        return schema.type();
    }

    public static ControlRecordType fromTypeId(short typeId) {
        switch (typeId) {

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Inspect the source segment with kafka-dump-log to confirm the malformed key.
  2. Verify the writing broker is a compatible Kafka version and shut down cleanly.
  3. Truncate or replace the corrupt segment / restore the KRaft snapshot from a healthy replica.
Defensive patterns

Strategy: validation

Validate before calling

// Validate buffer length before parsing the control record key (requires >= 4 bytes)
import java.nio.ByteBuffer;
import org.apache.kafka.common.record.ControlRecordType;

private static final int CONTROL_RECORD_KEY_SIZE = 4; // version(short) + type(short)

ByteBuffer dup = key.duplicate();
if (dup.remaining() >= CONTROL_RECORD_KEY_SIZE) {
    short typeId = ControlRecordType.parseTypeId(dup);
} else {
    // key is too short / corrupted; handle as bad data
}

Type guard

import java.nio.ByteBuffer;

static boolean hasControlRecordKeySize(ByteBuffer key) {
    return key != null && key.remaining() >= 4;
}

// usage: if (hasControlRecordKeySize(key)) { ControlRecordType.parseTypeId(key); }

Try / catch

try {
    short typeId = ControlRecordType.parseTypeId(key);
} catch (org.apache.kafka.common.InvalidRecordException e) {
    // key buffer is undersized; treat as corrupt/truncated control record
}

Prevention

When it happens

Trigger: Calling ControlRecordType.parse(key) or parseTypeId(key) on a control record whose key ByteBuffer has fewer than 4 bytes remaining; reached during consumer/replica/KRaft reads of transaction, commit, leader-change, snapshot, or voter control batches.

Common situations: Corrupted or truncated log segment on disk; partial write from a crashed broker; follower out of sync producing a short batch; manual tampering or a bad custom serializer.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/129b14086617c6fa.json. Report an issue: GitHub.