{"id":"1bc6e6b73f85818f","repo":"apache/kafka","slug":"rebalancelistener-cannot-be-null-1bc6e6","errorCode":null,"errorMessage":"RebalanceListener cannot be null","messagePattern":"RebalanceListener cannot be null","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/ClassicKafkaConsumer.java","lineNumber":442,"sourceCode":"            return Collections.unmodifiableSet(this.subscriptions.assignedPartitions());\n        } finally {\n            release();\n        }\n    }\n\n    public Set<String> subscription() {\n        acquireAndEnsureOpen();\n        try {\n            return Set.copyOf(this.subscriptions.subscription());\n        } finally {\n            release();\n        }\n    }\n\n    @Override\n    public void subscribe(Collection<String> topics, ConsumerRebalanceListener listener) {\n        if (listener == null)\n            throw new IllegalArgumentException(\"RebalanceListener cannot be null\");\n\n        subscribeInternal(topics, Optional.of(listener));\n    }\n\n\n    @Override\n    public void registerMetricForSubscription(KafkaMetric metric) {\n        if (!metrics().containsKey(metric.metricName())) {\n            clientTelemetryReporter.ifPresent(reporter -> reporter.metricChange(metric));\n        } else {\n            log.debug(\"Skipping registration for metric {}. Existing consumer metrics cannot be overwritten.\", metric.metricName());\n        }\n    }\n\n    @Override\n    public void unregisterMetricFromSubscription(KafkaMetric metric) {\n        if (!metrics().containsKey(metric.metricName())) {\n            clientTelemetryReporter.ifPresent(reporter -> reporter.metricRemoval(metric));","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ClassicKafkaConsumer.java#L424-L460","documentation":"Thrown by ClassicKafkaConsumer.subscribe(Collection<String>, ConsumerRebalanceListener) as an IllegalArgumentException when the listener argument is null. The classic consumer requires a non-null listener because partition assignment/revocation callbacks are the only way to learn about rebalance events on this API variant, and forwarding null would cause NPEs inside the coordinator during rebalance. The guard fails fast at the call site.","triggerScenarios":"Calling consumer.subscribe(topics, null) using the two-argument Collection overload; passing a listener field that has not been initialized (still null) at the call site; refactoring that moved listener construction after the subscribe call.","commonSituations":"Refactoring from subscribe(topics) to the listener variant and forgetting to instantiate the listener; conditional listener construction where one branch leaves it null; copy-paste of a code sample that omitted the listener instantiation; testing utilities that pass null for 'no listener' when the no-listener overload should be used instead.","solutions":["Pass a real ConsumerRebalanceListener instance, or use the single-argument subscribe(Collection) overload if you do not need callbacks.","Initialize the listener field before subscribe: this.listener = new MyRebalanceListener(); consumer.subscribe(topics, listener);","If the listener is optional in your design, branch: if (listener != null) subscribe(topics, listener); else subscribe(topics);","Add a null-check unit test at the wrapper layer to catch regressions."],"exampleFix":"// before\nconsumer.subscribe(topics, null);\n\n// after\nconsumer.subscribe(topics, new ConsumerRebalanceListener() {\n    @Override public void onPartitionsRevoked(Collection<TopicPartition> p) {}\n    @Override public void onPartitionsAssigned(Collection<TopicPartition> p) {}\n});\n// or simply: consumer.subscribe(topics);","handlingStrategy":"validation","validationCode":"// Provide a no-op listener when you have no rebalance logic, never null.\nConsumerRebalanceListener listener = (realListener != null)\n    ? realListener\n    : new ConsumerRebalanceListener() {\n        @Override public void onPartitionsRevoked(Collection<TopicPartition> p) {}\n        @Override public void onPartitionsAssigned(Collection<TopicPartition> p) {}\n    };\nconsumer.subscribe(topics, listener);","typeGuard":"static boolean hasRebalanceListener(ConsumerRebalanceListener l) {\n    return l != null;\n}","tryCatchPattern":"try {\n    consumer.subscribe(topics, listener);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"RebalanceListener cannot be null\")) {\n        consumer.subscribe(topics); // fall back to overload without listener\n    } else {\n        throw e;\n    }\n}","preventionTips":["If you have no rebalance handling, call subscribe(topics) (the no-listener overload) instead of passing null.","Inject listeners via constructor/DI so a null reference surfaces as a wiring failure, not a runtime exception.","Annotate your wrapper parameter with @NotNull (javax.validation) to catch null at the boundary."],"tags":["kafka","consumer","classic-consumer","subscribe","rebalance-listener","validation"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}