apache/pulsar · error · java.lang.IllegalArgumentException
Invalid key-shared mode: ${keySharedMode}
Error message
Invalid key-shared mode: ${keySharedMode} What it means
When a Key_Shared subscription dispatcher is created, the broker instantiates a StickyKeyConsumerSelector based on the subscription's KeySharedMode. Only STICKY and AUTO_SPLIT selectors are implemented; any other mode value falls into the default branch and throws IllegalArgumentException. This is a defensive guard against unsupported/unknown KeySharedMode enum values reaching the dispatcher constructor.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentStickyKeyDispatcherMultipleConsumersClassic.java:140
switch (this.keySharedMode) {
case AUTO_SPLIT:
if (conf.isSubscriptionKeySharedUseConsistentHashing()) {
selector = new ConsistentHashingStickyKeyConsumerSelector(
conf.getSubscriptionKeySharedConsistentHashingReplicaPoints(),
false,
// Classic implementation uses Integer.MAX_VALUE - 1 as the range end value
Integer.MAX_VALUE - 1);
} else {
selector = new HashRangeAutoSplitStickyKeyConsumerSelector();
}
break;
case STICKY:
this.selector = new HashRangeExclusiveStickyKeyConsumerSelector();
break;
default:
throw new IllegalArgumentException("Invalid key-shared mode: " + keySharedMode);
}
}
@VisibleForTesting
public StickyKeyConsumerSelector getSelector() {
return selector;
}
@Override
public synchronized CompletableFuture<Void> addConsumer(Consumer consumer) {
if (IS_CLOSED_UPDATER.get(this) == TRUE) {
log.warn()
.attr("consumer", consumer)
.log("Dispatcher is already closed. Closing consumer");
consumer.disconnect();
return CompletableFuture.completedFuture(null);
}
return super.addConsumer(consumer).thenCompose(__ ->View on GitHub (pinned to 820761864e)
Solutions
- Disable the classic implementation (remove subscriptionKeySharedUseClassicImplementation=true or set it to false) so the modern KeyShared dispatcher handles the mode
- Align broker versions across the cluster so all brokers support the KeySharedMode in use
- Check the subscription's policies and explicitly set KeySharedMode to STICKY or AUTO_SPLIT (e.g. via setSubscriptionKeySharedType on the admin API)
- Clear/repair the subscription policy data if it contains an unknown mode value
Example fix
// before (broker.conf) subscriptionKeySharedUseClassicImplementation=true // after (broker.conf) subscriptionKeySharedUseClassicImplementation=false
Defensive patterns
Strategy: validation
Validate before calling
KeySharedMode mode = policies.getKeySharedMode();
if (mode != KeySharedMode.AUTO_SPLIT && mode != KeySharedMode.STICKY) {
throw new IllegalArgumentException("Unsupported KeySharedMode for classic dispatcher: " + mode);
} Type guard
boolean isSupportedKeySharedMode(KeySharedMode m) {
return m == KeySharedMode.AUTO_SPLIT || m == KeySharedMode.STICKY;
} Try / catch
try {
dispatcher = new PersistentStickyKeyDispatcherMultipleConsumersClassic(...);
} catch (IllegalArgumentException e) {
log.error("KeyShared dispatcher creation failed: {}", e.getMessage());
// fall back to non-classic dispatcher or fail subscription setup
} Prevention
- Do not enable subscriptionKeySharedUseClassicImplementation in clusters running brokers with newer KeySharedMode values
- Pin all brokers to the same Pulsar version
- Always set KeySharedMode explicitly to STICKY or AUTO_SPLIT in topic policies
When it happens
Trigger: Creating a PersistentStickyKeyDispatcherMultipleConsumersClassic for a Key_Shared subscription whose KeySharedMode is neither AUTO_SPLIT nor STICKY — typically when a policy/store contains a newer enum value (e.g. from a newer broker/client version) that the classic dispatcher implementation does not support, or corrupted subscription properties.
Common situations: Clusters with mixed broker versions where a topic's KeySharedMode was set by a newer broker, then handled by a broker running subscriptionKeySharedUseClassicImplementation=true; hand-edited or migrated topic policy data; client producers/consumers negotiating a mode the classic dispatcher predates.
Related errors
- The topic has a max partition index of %d, the number of par
- entryFilterNames can't be empty. To remove entry filters use
- The offloadPolicies must be specified for namespace offload.
- The driver is not supported, support value: ${supportedDrive
- The bucket must be specified for namespace offload.
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/94d951c381510034.
Report an issue: GitHub.