apache/kafka · error · java.lang.UnsupportedOperationException
Subscribe to RE2/J pattern is not supported when usingthe %s
Error message
Subscribe to RE2/J pattern is not supported when usingthe %s protocol defined in config %s
What it means
Thrown by ClassicKafkaConsumer.subscribe(SubscriptionPattern, ...) as an UnsupportedOperationException. SubscriptionPattern is the KIP-848 RE2/J-based regex subscription API and is only implemented by the async consumer (group.protocol=consumer). When the classic protocol is selected the method is unsupported by design; the message interpolates GroupProtocol.CLASSIC and ConsumerConfig.GROUP_PROTOCOL_CONFIG so the user knows exactly which config to change. Note the literal source string is missing a space before 'the' ('usingthe'), but the runtime format renders it as-is.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/ClassicKafkaConsumer.java:542
}
}
@Override
public void subscribe(Pattern pattern, ConsumerRebalanceListener listener) {
if (listener == null)
throw new IllegalArgumentException("RebalanceListener cannot be null");
subscribeInternal(pattern, Optional.of(listener));
}
@Override
public void subscribe(Pattern pattern) {
subscribeInternal(pattern, Optional.empty());
}
@Override
public void subscribe(SubscriptionPattern pattern, ConsumerRebalanceListener callback) {
throw new UnsupportedOperationException(String.format("Subscribe to RE2/J pattern is not supported when using" +
"the %s protocol defined in config %s", GroupProtocol.CLASSIC, ConsumerConfig.GROUP_PROTOCOL_CONFIG));
}
@Override
public void subscribe(SubscriptionPattern pattern) {
throw new UnsupportedOperationException(String.format("Subscribe to RE2/J pattern is not supported when using" +
"the %s protocol defined in config %s", GroupProtocol.CLASSIC, ConsumerConfig.GROUP_PROTOCOL_CONFIG));
}
/**
* Internal helper method for {@link #subscribe(Pattern)} and
* {@link #subscribe(Pattern, ConsumerRebalanceListener)}
* <p>
* Subscribe to all topics matching specified pattern to get dynamically assigned partitions.
* The pattern matching will be done periodically against all topics existing at the time of check.
* This can be controlled through the {@code metadata.max.age.ms} configuration: by lowering
* the max metadata age, the consumer will refresh metadata more often and check for matching topics.
* <p>View on GitHub (pinned to c31c9215e1)
Solutions
- Set group.protocol=consumer (GroupProtocol.CONSUMER) in the consumer config so the async consumer, which implements SubscriptionPattern, is instantiated.
- If you must stay on the classic protocol, use the JDK Pattern overload instead: consumer.subscribe(Pattern.compile("orders\\..*"));
- Audit framework adapters (Spring Kafka, Kafka Streams wrappers) that may call SubscriptionPattern and ensure they select the consumer protocol when they do.
- Update docs/readmes that reference the RE2/J pattern API to also mandate group.protocol=consumer.
Example fix
// before
props.put(ConsumerConfig.GROUP_PROTOCOL_CONFIG, "classic");
new KafkaConsumer<String,String>(props).subscribe(new SubscriptionPattern("orders\\\\..*"));
// after
props.put(ConsumerConfig.GROUP_PROTOCOL_CONFIG, "consumer");
new KafkaConsumer<String,String>(props).subscribe(new SubscriptionPattern("orders\\\\..*")); Defensive patterns
Strategy: fallback
Validate before calling
// Detect classic protocol at startup and skip the RE2/J SubscriptionPattern API.
String proto = String.valueOf(props.getOrDefault(
ConsumerConfig.GROUP_PROTOCOL_CONFIG, GroupProtocol.CLASSIC.name()));
boolean isClassic = GroupProtocol.CLASSIC.name().equalsIgnoreCase(proto);
if (isClassic && pattern instanceof SubscriptionPattern) {
throw new UnsupportedOperationException(
"SubscriptionPattern (RE2/J) requires the CONSUMER group protocol; " +
"use java.util.regex.Pattern with classic consumer, or switch group.protocol.config");
} Type guard
// Distinguish the two Pattern types at the call boundary.
static boolean isSubscriptionPatternRe2j(Object p) {
return p instanceof org.apache.kafka.clients.consumer.SubscriptionPattern;
}
// route:
if (isSubscriptionPatternRe2j(pattern)) {
// only valid on AsyncKafkaConsumer with CONSUMER protocol
} else {
consumer.subscribe((java.util.regex.Pattern) pattern);
} Try / catch
try {
consumer.subscribe(subscriptionPattern, callback);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("RE2/J")) {
// Fall back to java.util.regex.Pattern overload on classic consumer.
consumer.subscribe(java.util.regex.Pattern.compile(subscriptionPattern.pattern()), callback);
} else {
throw e;
}
} Prevention
- SubscriptionPattern (RE2/J) is only honored on the async consumer with group.protocol=consumer; classic does not support it.
- Pick the Pattern overload (java.util.regex) for classic consumers; reserve SubscriptionPattern for the new async API.
- Branch your subscribe wrapper on the configured GroupProtocol so the wrong overload is never reached.
- Document at the wrapper level which protocol your application uses, so RE2/J misuse fails in review.
When it happens
Trigger: Calling consumer.subscribe(new SubscriptionPattern("orders\\..*")) (with or without a callback) on a KafkaConsumer built with group.protocol=classic (the default). Also triggered by frameworks that auto-detect SubscriptionPattern support and call the new API regardless of the configured group protocol.
Common situations: Adopting the RE2/J SubscriptionPattern API from examples/docs without also switching group.protocol to consumer; mixed-protocol code paths where some consumers are classic and others async; library code that calls subscribe(SubscriptionPattern) unconditionally; upgrading the client jar and picking up the new API surface before updating config.
Related errors
- RebalanceListener cannot be null
- Topic collection to subscribe to cannot be null
- Topic collection to subscribe to cannot contain null or empt
- {invalidConfigs} cannot be set when group.protocol={groupPro
- Topic pattern to subscribe to cannot be null
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/09b229f76ad0ebbb.json.
Report an issue: GitHub.