{"id":"a698524a2fb9d879","repo":"apache/kafka","slug":"topic-partitions-to-assign-to-cannot-have-null-or","errorCode":null,"errorMessage":"Topic partitions to assign to cannot have null or empty topic","messagePattern":"Topic partitions to assign to cannot have null or empty topic","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java","lineNumber":1902,"sourceCode":"    }\n\n    @Override\n    public void assign(Collection<TopicPartition> partitions) {\n        acquireAndEnsureOpen();\n        try {\n            if (partitions == null) {\n                throw new IllegalArgumentException(\"Topic partitions collection to assign to cannot be null\");\n            }\n\n            if (partitions.isEmpty()) {\n                unsubscribe();\n                return;\n            }\n\n            for (TopicPartition tp : partitions) {\n                String topic = (tp != null) ? tp.topic() : null;\n                if (isBlank(topic))\n                    throw new IllegalArgumentException(\"Topic partitions to assign to cannot have null or empty topic\");\n            }\n\n            // Clear the buffered data which are not a part of newly assigned topics\n            final Set<TopicPartition> currentTopicPartitions = new HashSet<>();\n\n            for (TopicPartition tp : subscriptions.assignedPartitions()) {\n                if (partitions.contains(tp))\n                    currentTopicPartitions.add(tp);\n            }\n\n            fetchBuffer.retainAll(currentTopicPartitions);\n\n            // assignment change event will trigger autocommit if it is configured and the group id is specified. This is\n            // to make sure offsets of topic partitions the consumer is unsubscribing from are committed since there will\n            // be no following rebalance.\n            //\n            // See the ApplicationEventProcessor.process() method that handles this event for more detail.\n            applicationEventHandler.addAndGet(new AssignmentChangeEvent(","sourceCodeStart":1884,"sourceCodeEnd":1920,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java#L1884-L1920","documentation":"Thrown by KafkaConsumer.assign(Collection<TopicPartition>) when the passed collection is non-null and non-empty but contains a TopicPartition whose topic name is null, empty, or whitespace-only. The client validates every TopicPartition before publishing an AssignmentChangeEvent so the background network thread never has to deal with malformed partition metadata. It is a programmer error, not a transient runtime condition.","triggerScenarios":"Calling consumer.assign(Arrays.asList(new TopicPartition(null, 0))), passing a TopicPartition built from an uninitialized String field, or building the collection from a stream/map that yields null or \"\" topic names. Any element where TopicPartition.topic() returns a blank string triggers it; a wholly null TopicPartition element also triggers it because tp.topic() would be reached only after the null check at line 1900.","commonSituations":"Topic name read from a misconfigured property file or environment variable that resolved to empty; deserializing partitions from JSON/YAML where a field was omitted; refactoring code that previously used String topic names and forgetting to populate the field; unit tests that construct TopicPartition placeholders.","solutions":["Validate each topic name before building the TopicPartition: filter out null/blank strings or fail fast with a clear upstream error.","Log the offending TopicPartition (toString) in a wrapping try/catch to identify which element is malformed.","If the topic list comes from configuration, ensure the property is non-empty and trim whitespace before use.","Add a unit test that asserts assign() receives only well-formed TopicPartition objects."],"exampleFix":"// before\nList<TopicPartition> parts = topics.stream()\n    .map(t -> new TopicPartition(t, 0))\n    .collect(Collectors.toList());\nconsumer.assign(parts);\n\n// after\nList<TopicPartition> parts = topics.stream()\n    .filter(t -> t != null && !t.trim().isEmpty())\n    .map(t -> new TopicPartition(t.trim(), 0))\n    .collect(Collectors.toList());\nif (parts.isEmpty()) throw new IllegalArgumentException(\"no valid topics\");\nconsumer.assign(parts);","handlingStrategy":"validation","validationCode":"// Before consumer.assign(partitions):\nif (partitions == null) throw new IllegalArgumentException(\"partitions is null\");\nfor (TopicPartition tp : partitions) {\n    if (tp == null || tp.topic() == null || tp.topic().trim().isEmpty()) {\n        throw new IllegalArgumentException(\"TopicPartition has null/blank topic: \" + tp);\n    }\n}\nconsumer.assign(partitions);","typeGuard":"// Java: ensure every TopicPartition is well-formed\nstatic boolean isWellFormed(TopicPartition tp) {\n    return tp != null && tp.topic() != null && !tp.topic().trim().isEmpty()\n        && tp.partition() >= 0;\n}\n// filter: partitions.removeIf(tp -> !isWellFormed(tp));","tryCatchPattern":"// Not recommended: validate before assign() rather than catching.\n// If unavoidable:\ntry {\n    consumer.assign(partitions);\n} catch (IllegalArgumentException e) {\n    // log, drop offending TopicPartition, or fail-fast upstream\n    log.error(\"Invalid assignment\", e);\n    throw e;\n}","preventionTips":["Sanitize TopicPartition collections at the boundary where they are built (e.g. from config or external input).","Never construct TopicPartition with a topic literal that could be null; use Constants.requireNonNull or Objects.requireNonNull on the topic name.","If topics come from a dynamic source, validate them against an allow-list before building TopicPartition objects.","Unit-test assignment code paths with null entries and blank topic names."],"tags":["consumer","assign","validation","illegal-argument","java"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}