apache/kafka · error · IllegalArgumentException
Headers cannot be null
Error message
Headers cannot be null
What it means
Thrown by the ConsumerRecord constructor when the headers argument is null. Kafka records always carry a Headers container (possibly empty), and downstream code assumes it can iterate or mutate headers without null checks. The constructor enforces a non-null Headers, defaulting to empty if you have none.
Solutions
- Pass new RecordHeaders() when you have no headers, never null.
- In interceptors, copy the original headers via record.headers() or a fresh RecordHeaders(copyOf(original)).
- Add a helper that always supplies an empty Headers default to fixture builders.
Example fix
// before
new ConsumerRecord<>("orders", 0, 0L, key, value, null);
// after
import org.apache.kafka.common.header.internals.RecordHeaders;
new ConsumerRecord<>("orders", 0, 0L, key, value, new RecordHeaders()); Defensive patterns
Strategy: validation
Validate before calling
Headers h = headers != null ? headers : new RecordHeaders(); new ConsumerRecord<>(topic, partition, offset, key, value, h);
Type guard
static Headers requireHeaders(Headers h) {
return h != null ? h : new RecordHeaders();
} Try / catch
try {
return new ConsumerRecord<>(topic, partition, offset, key, value, headers);
} catch (IllegalArgumentException e) {
if ("Headers cannot be null".equals(e.getMessage())) {
return new ConsumerRecord<>(topic, partition, offset, key, value, new RecordHeaders());
}
throw e;
} Prevention
- Default headers to new RecordHeaders() in any record-building helper.
- In interceptors, copy original.headers() into the new record rather than passing null.
- Add a unit test that exercises the no-headers code path through the helper.
When it happens
Trigger: Constructing a ConsumerRecord with headers=null in tests or custom adapters; an interceptor replacing a record and forgetting to carry headers forward; copying a record with a RecordHeaders-stripping mapper.
Common situations: Test fixtures for ConsumerRecord; bridge code from a non-Kafka message system that has no header concept; serializer/interceptor middleware that rebuilds records.
Related errors
- Topic cannot be null
- RebalanceListener cannot be null
- Topic must be non-null.
- Cannot add records for a partition that is not assigned to…
- Cannot lose partitions that are not currently assigned
AI-assisted analysis of apache/kafka@996fb4585a (2026-08-11).
Data as JSON: /api/errors/581c85aab5e8d043.
Report an issue: GitHub.
Appendix: 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 996fb4585a)