{"record":{"id":"c839c6b7d2572275","repo":"apache/kafka","slug":"topic-must-be-non-null","errorCode":null,"errorMessage":"Topic must be non-null.","messagePattern":"Topic must be non-null\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecords.java","lineNumber":122,"sourceCode":"            // every call. A time based approach is used to avoid this. See KAFKA-20660 for more details.\n            if (now - lastLog >= TAINT_LOG_INTERVAL_NS && TAINTED_NEXT_OFFSETS_LAST_LOG_NS.compareAndSet(lastLog, now)) {\n                log.error(\"ConsumerRecords#nextOffsets() returned empty because this instance was built with the \" +\n                        \"deprecated ConsumerRecords(Map) constructor (see KIP-1094), which does not supply next offsets. \" +\n                        \"Downstream logic that relies on these offsets to advance the consumer's committed position \" +\n                        \"(for example, Kafka Streams under exactly-once semantics) will be unable to commit, leading to \" +\n                        \"reprocessing. Update the interceptor or wrapper that constructed it to use the \" +\n                        \"ConsumerRecords(Map, Map) constructor that supplies next offsets.\");\n            }\n        }\n        return nextOffsets;\n    }\n\n    /**\n     * Get just the records for the given topic\n     */\n    public Iterable<ConsumerRecord<K, V>> records(String topic) {\n        if (topic == null)\n            throw new IllegalArgumentException(\"Topic must be non-null.\");\n        List<List<ConsumerRecord<K, V>>> recs = new ArrayList<>();\n        for (Map.Entry<TopicPartition, List<ConsumerRecord<K, V>>> entry : records.entrySet()) {\n            if (entry.getKey().topic().equals(topic))\n                recs.add(entry.getValue());\n        }\n        return new ConcatenatedIterable<>(recs);\n    }\n\n    /**\n     * Get the partitions which have records contained in this record set.\n     * @return The set of partitions with data in this record set (may be empty if no data was returned)\n     */\n    public Set<TopicPartition> partitions() {\n        return Collections.unmodifiableSet(records.keySet());\n    }\n\n    @Override\n    public Iterator<ConsumerRecord<K, V>> iterator() {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/apache/kafka/blob/996fb4585aa1bcc8980b0e1b8d6b168b986cd979/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecords.java#L104-L140","documentation":"Thrown by ConsumerRecords.records(String topic) when the topic argument is null. The method filters the records map by topic equality, and a null topic would never match (and would be ambiguous), so Kafka rejects it up front. Pass the topic you want records for; if you want everything, use the iterator or .count() instead.","triggerScenarios":"Calling consumer.poll(...).records(topic) where topic is a variable that resolved to null; passing a topic name pulled from a config/property that was unset; looping over a collection of topic names where one entry is null.","commonSituations":"Apps that read target topics from external config and forget a default; helper methods that accept a nullable topic parameter; tests with placeholder topic variables.","solutions":["Validate the topic string is non-null before calling records(topic); guard with Objects.requireNonNull(topic, \"topic\").","Load the topic name from a config key with a sane default and fail fast at startup if missing.","If you want all records, iterate ConsumerRecords directly instead of calling records(topic)."],"exampleFix":"// before\nIterable<ConsumerRecord<K,V>> recs = polled.records(topicFromConfig); // topicFromConfig == null\n\n// after\nString topic = Objects.requireNonNull(topicFromConfig, \"topic must be configured\");\nIterable<ConsumerRecord<K,V>> recs = polled.records(topic);","handlingStrategy":"validation","validationCode":"String safeTopic = Objects.requireNonNull(topic, \"topic must be non-null before records(topic)\");\nreturn polled.records(safeTopic);","typeGuard":"static boolean isQueryableTopic(String t) {\n    return t != null && !t.isEmpty();\n}","tryCatchPattern":"try {\n    return polled.records(topic);\n} catch (IllegalArgumentException e) {\n    if (\"Topic must be non-null.\".equals(e.getMessage())) {\n        return Collections.emptyList(); // or surface as a configuration error\n    }\n    throw e;\n}","preventionTips":["Validate topic config at application startup with a fail-fast check.","Wrap records(topic) usage in a helper that requires non-null topic.","Use ConsumerRecords.iterator() when you want all records regardless of topic."],"tags":["consumer","consumer-records","null-check","api-misuse"],"backgroundTag":null,"analyzedSha":"996fb4585aa1bcc8980b0e1b8d6b168b986cd979","analyzedAt":"2026-08-11T22:03:28.655Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}