apache/kafka · error · IllegalArgumentException
RebalanceListener cannot be null
Error message
RebalanceListener cannot be null
What it means
Thrown by MockConsumer.subscribe(Pattern, ConsumerRebalanceListener) when the listener argument is null. This overload explicitly takes a listener (unlike the no-listener overloads that pass null internally), and Kafka requires the listener because rebalance callbacks are the whole point of supplying one. If you do not need callbacks, call the single-arg subscribe(Pattern) overload instead.
Solutions
- Pass a real ConsumerRebalanceListener (e.g. a no-op stub) when calling the two-arg overload.
- If you have no callbacks, switch to the single-arg subscribe(Pattern) overload.
- Initialize the listener field before subscribing; assert it is non-null in a @BeforeEach.
Example fix
// before
mockConsumer.subscribe(Pattern.compile("orders-.*"), null);
// after
// option A: no listener needed
mockConsumer.subscribe(Pattern.compile("orders-.*"));
// option B: supply a stub
mockConsumer.subscribe(Pattern.compile("orders-.*"), new ConsumerRebalanceListener() {
@Override public void onPartitionsRevoked(Collection<TopicPartition> p) {}
@Override public void onPartitionsAssigned(Collection<TopicPartition> p) {}
}); Defensive patterns
Strategy: validation
Validate before calling
ConsumerRebalanceListener listener = Objects.requireNonNull(listenerArg, "listener"); mockConsumer.subscribe(pattern, listener);
Type guard
static boolean hasListener(ConsumerRebalanceListener l) {
return l != null;
} Try / catch
try {
mockConsumer.subscribe(pattern, listener);
} catch (IllegalArgumentException e) {
if ("RebalanceListener cannot be null".equals(e.getMessage())) {
mockConsumer.subscribe(pattern, new NoOpConsumerRebalanceListener()); // or use single-arg overload
} else throw e;
} Prevention
- Initialize the listener field in @BeforeEach.
- If no callbacks are needed, prefer the single-arg subscribe(Pattern) overload.
- Keep a NoOpConsumerRebalanceListener stub available for tests.
When it happens
Trigger: Passing a null rebalance listener to the (Pattern, listener) overload; passing a listener variable that was never initialized; copy-paste from code that conditionally supplies a listener.
Common situations: Tests that subscribe with a stub listener field that defaulted to null; refactor that removed listener initialization but kept the two-arg call.
Related errors
- Topic pattern cannot be
- Cannot add records for a partition that is not assigned to…
- Cannot lose partitions that are not currently assigned
- clientInstanceId not set
- MaxPollRecords must be strictly superior to 0
AI-assisted analysis of apache/kafka@996fb4585a (2026-08-11).
Data as JSON: /api/errors/088d30e05e3347fa.
Report an issue: GitHub.
Appendix: source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/MockConsumer.java:194
.filter(tp -> !lost.contains(tp))
.collect(Collectors.toSet());
this.subscriptions.assignFromSubscribed(remaining);
}
@Override
public synchronized Set<String> subscription() {
return subscriptions.subscription();
}
@Override
public synchronized void subscribe(Collection<String> topics) {
subscribeInternal(topics, null);
}
@Override
public synchronized void subscribe(Pattern pattern, final ConsumerRebalanceListener listener) {
if (listener == null)
throw new IllegalArgumentException("RebalanceListener cannot be null");
subscribeInternal(pattern, listener);
}
@Override
public synchronized void subscribe(Pattern pattern) {
subscribeInternal(pattern, null);
}
@Override
public synchronized void subscribe(SubscriptionPattern pattern, ConsumerRebalanceListener listener) {
if (listener == null)
throw new IllegalArgumentException("RebalanceListener cannot be null");
subscribeInternal(pattern, listener);
}
@OverrideView on GitHub (pinned to 996fb4585a)