apache/kafka · error · IllegalArgumentException

Cannot serialize UNKNOWN control record type

Error message

Cannot serialize UNKNOWN control record type

What it means

ControlRecordType.recordKey() (line 77) refuses to serialise the UNKNOWN sentinel. UNKNOWN (typeId -1) is a catch-all for control record typeIds the client does not recognise and is intended only for inbound parsing; it has no on-wire serialised form. Re-emitting it would produce a meaningless key, so the library blocks it with IllegalArgumentException.

Source

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

    private static final Logger log = LoggerFactory.getLogger(ControlRecordType.class);
    private static final int CONTROL_RECORD_KEY_SIZE = 4;

    private final short type;
    private final ByteBuffer buffer;

    ControlRecordType(short type) {
        this.type = type;
        ControlRecordTypeSchema schema = new ControlRecordTypeSchema().setType(type);
        buffer = MessageUtil.toVersionPrefixedByteBuffer(ControlRecordTypeSchema.HIGHEST_SUPPORTED_VERSION, schema);
    }

    public short type() {
        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 +

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Filter out or skip UNKNOWN before serialising (treat it as 'ignore').
  2. Map the unknown typeId to a concrete known type, or drop the record instead of re-keying it.
  3. Upgrade the producing client to a version that recognises the typeId so it parses to a concrete type.

Example fix

// before
ByteBuffer key = controlRecordType.recordKey();
// after
if (controlRecordType == ControlRecordType.UNKNOWN) {
    throw new IllegalStateException("Refusing to re-serialise UNKNOWN control record");
}
ByteBuffer key = controlRecordType.recordKey();
Defensive patterns

Strategy: type-guard

Validate before calling

// Never serialize UNKNOWN; guard before calling recordKey()
import org.apache.kafka.common.record.ControlRecordType;
if (controlRecordType != ControlRecordType.UNKNOWN) {
    ByteBuffer key = controlRecordType.recordKey();
} else {
    // UNKNOWN is a sentinel for unrecognized types; it cannot be serialized
}

Type guard

import org.apache.kafka.common.record.ControlRecordType;

static boolean isSerializable(ControlRecordType t) {
    return t != ControlRecordType.UNKNOWN;
}

// usage: if (isSerializable(type)) { buf = type.recordKey(); }

Try / catch

try {
    ByteBuffer key = controlRecordType.recordKey();
} catch (IllegalArgumentException e) {
    // attempted to serialize UNKNOWN; skip or reject the record
}

Prevention

When it happens

Trigger: Calling ControlRecordType.UNKNOWN.recordKey(); building a control record batch whose type came from fromTypeId() of an unrecognised id and then writing it back out; generic code that round-trips any parsed ControlRecordType through a producer/mirror.

Common situations: Mirror/replication tooling that re-emits control records of newer types an older client doesn't know; code that treats UNKNOWN as a real type.

Related errors


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