apache/kafka · error · IllegalArgumentException
Topic must be non-null.
Error message
Topic must be non-null.
What it means
IllegalArgumentException thrown by ConsumerRecords.records(String topic) when the topic argument is null. The lookup compares each partition's topic via equals(), so a null topic would never match and is treated as a programming error.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecords.java:122
// every call. A time based approach is used to avoid this. See KAFKA-20660 for more details.
if (now - lastLog >= TAINT_LOG_INTERVAL_NS && TAINTED_NEXT_OFFSETS_LAST_LOG_NS.compareAndSet(lastLog, now)) {
log.error("ConsumerRecords#nextOffsets() returned empty because this instance was built with the " +
"deprecated ConsumerRecords(Map) constructor (see KIP-1094), which does not supply next offsets. " +
"Downstream logic that relies on these offsets to advance the consumer's committed position " +
"(for example, Kafka Streams under exactly-once semantics) will be unable to commit, leading to " +
"reprocessing. Update the interceptor or wrapper that constructed it to use the " +
"ConsumerRecords(Map, Map) constructor that supplies next offsets.");
}
}
return nextOffsets;
}
/**
* Get just the records for the given topic
*/
public Iterable<ConsumerRecord<K, V>> records(String topic) {
if (topic == null)
throw new IllegalArgumentException("Topic must be non-null.");
List<List<ConsumerRecord<K, V>>> recs = new ArrayList<>();
for (Map.Entry<TopicPartition, List<ConsumerRecord<K, V>>> entry : records.entrySet()) {
if (entry.getKey().topic().equals(topic))
recs.add(entry.getValue());
}
return new ConcatenatedIterable<>(recs);
}
/**
* Get the partitions which have records contained in this record set.
* @return The set of partitions with data in this record set (may be empty if no data was returned)
*/
public Set<TopicPartition> partitions() {
return Collections.unmodifiableSet(records.keySet());
}
@Override
public Iterator<ConsumerRecord<K, V>> iterator() {View on GitHub (pinned to c31c9215e1)
Solutions
- Validate the topic variable is non-null before calling records(topic).
- Ensure the source feeding the topic name (config, request param, map key) actually contains it.
- Default or skip with an explicit empty check: if (topic != null) { for (Record r : cr.records(topic)) ... }.
Example fix
// before
Iterable<ConsumerRecord<K,V>> recs = consumerRecords.records(maybeTopic);
// after
if (maybeTopic == null) throw new IllegalStateException("topic not configured");
Iterable<ConsumerRecord<K,V>> recs = consumerRecords.records(maybeTopic); Defensive patterns
Strategy: validation
Validate before calling
if (topic == null) {
throw new IllegalArgumentException("topic must be non-null for ConsumerRecords.records(topic)");
}
Iterable<ConsumerRecord<K,V>> recs = consumerRecords.records(topic); Try / catch
try {
consumerRecords.records(topic);
} catch (IllegalArgumentException e) {
if ("Topic must be non-null.".equals(e.getMessage())) {
// topic came from external input — default to iterating consumerRecords.partitions() instead
}
throw e;
} Prevention
- Prefer iterating `consumerRecords.partitions()` and filtering by TopicPartition when the topic source is untrusted.
- Null-check any topic variable sourced from request params, configs, or maps before calling .records(topic).
- Wrap ConsumerRecords usage in a helper that rejects null topics at the boundary.
When it happens
Trigger: Calling consumerRecords.records(topicVar) where topicVar is null; passing a topic sourced from an Optional/Map.get that returned null without a guard.
Common situations: Topic name read from external config that is missing; code branching on a topic string that was never set; loop variables that resolve to null for empty iteration.
Related errors
- Topic cannot be null
- Headers cannot be null
- Partitions collection cannot be null
- Invalid value null for configuration key.deserializer: must
- Invalid value null for configuration value.deserializer: mus
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/c839c6b7d2572275.json.
Report an issue: GitHub.