apache/kafka · error · IllegalArgumentException
Headers cannot be null
Error message
Headers cannot be null
What it means
IllegalArgumentException thrown by the ConsumerRecord constructor when headers is null. Kafka guarantees every record carries a (possibly empty) Headers instance; null headers would cause NPEs downstream in interceptors, serializers, and metrics.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecord.java:155
* @param leaderEpoch Optional leader epoch of the record (may be empty for legacy record formats)
* @param deliveryCount Optional delivery count of the record (may be empty when deliveries not counted)
*/
public ConsumerRecord(String topic,
int partition,
long offset,
long timestamp,
TimestampType timestampType,
int serializedKeySize,
int serializedValueSize,
K key,
V value,
Headers headers,
Optional<Integer> leaderEpoch,
Optional<Short> deliveryCount) {
if (topic == null)
throw new IllegalArgumentException("Topic cannot be null");
if (headers == null)
throw new IllegalArgumentException("Headers cannot be null");
this.topic = topic;
this.partition = partition;
this.offset = offset;
this.timestamp = timestamp;
this.timestampType = timestampType;
this.serializedKeySize = serializedKeySize;
this.serializedValueSize = serializedValueSize;
this.key = key;
this.value = value;
this.headers = headers;
this.leaderEpoch = leaderEpoch;
this.deliveryCount = deliveryCount;
}
/**
* The topic this record is received from (never null)
*/View on GitHub (pinned to c31c9215e1)
Solutions
- Pass a new RecordHeaders() (empty) rather than null when no headers are needed.
- If rebuilding a record inside an interceptor, propagate the original record.headers() instead of null.
- Switch to a constructor overload that supplies headers explicitly.
Example fix
// before
new ConsumerRecord<>("t", 0, 0L, 0L, TimestampType.CREATE_TIME, 0, 0, k, v, null);
// after
import org.apache.kafka.common.header.internals.RecordHeaders;
new ConsumerRecord<>("t", 0, 0L, 0L, TimestampType.CREATE_TIME, 0, 0, k, v, new RecordHeaders()); Defensive patterns
Strategy: validation
Validate before calling
// Never pass null headers; substitute an empty headers container Headers safeHeaders = (headers != null) ? headers : new RecordHeaders(); new ConsumerRecord<>(topic, partition, offset, timestamp, timestampType, keySize, valSize, key, value, safeHeaders, leaderEpoch);
Try / catch
try {
new ConsumerRecord<>(topic, partition, offset, /*...*/ key, value, headers, leaderEpoch);
} catch (IllegalArgumentException e) {
if ("Headers cannot be null".equals(e.getMessage())) {
headers = new RecordHeaders();
// retry construction
}
throw e;
} Prevention
- Always default headers to `new RecordHeaders()` rather than null when synthesizing records.
- In deserializers/interceptors that forward records, never strip the headers field.
- If a Record template lacks headers, add a precondition in its builder.
When it happens
Trigger: Constructing ConsumerRecord without passing a RecordHeaders instance (commonly a 9-arg/legacy overload where headers defaulted elsewhere, or hand-built records in tests/deserializers).
Common situations: Test fixtures using a constructor that omits headers; custom deserializers rebuilding records with null headers; bridging from a non-Kafka source that has no header concept.
Related errors
- Topic cannot be null
- Topic must be non-null.
- Failed to construct kafka consumer
- Partitions collection cannot be null
- RecordHeaders has been closed.
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/581c85aab5e8d043.json.
Report an issue: GitHub.