apache/pulsar · error · java.lang.IllegalArgumentException
Invalid key-shared mode: ${keySharedMode}
Error message
Invalid key-shared mode: ${keySharedMode} What it means
The broker's Key_Shared dispatcher only supports the AUTO_SPLIT and STICKY key-shared modes. createSelector switches on KeySharedMeta.getKeySharedMode() and throws IllegalArgumentException for any other value (or an unset/null mode that resolves to nothing handled). The switch exhaustively handles the two defined modes, so hitting the default means the subscription metadata carries a mode the broker doesn't recognize or support.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentStickyKeyDispatcherMultipleConsumers.java:122
topic.getBrokerService().executor(), this::cancelPendingRead, () -> reScheduleReadInMs(0),
() -> havePendingRead, this::getReadMoreEntriesCallCount, () -> !redeliveryMessages.isEmpty());
this.selector = selector;
}
private static StickyKeyConsumerSelector createSelector(KeySharedMeta ksm, ServiceConfiguration conf) {
boolean drainingHashesRequired =
ksm.getKeySharedMode() == KeySharedMode.AUTO_SPLIT && !ksm.isAllowOutOfOrderDelivery();
switch (ksm.getKeySharedMode()) {
case AUTO_SPLIT:
if (conf.isSubscriptionKeySharedUseConsistentHashing()) {
return new ConsistentHashingStickyKeyConsumerSelector(
conf.getSubscriptionKeySharedConsistentHashingReplicaPoints(), drainingHashesRequired);
}
return new HashRangeAutoSplitStickyKeyConsumerSelector(drainingHashesRequired);
case STICKY:
return new HashRangeExclusiveStickyKeyConsumerSelector();
default:
throw new IllegalArgumentException("Invalid key-shared mode: " + ksm.getKeySharedMode());
}
}
private void stickyKeyHashUnblocked(int stickyKeyHash) {
if (stickyKeyHash > -1) {
log.debug()
.attr("stickyKeyHash", stickyKeyHash)
.log("Sticky key hash is unblocked");
} else {
log.debug("Some sticky key hashes are unblocked");
}
reScheduleReadWithKeySharedUnblockingInterval();
}
private void reScheduleReadWithKeySharedUnblockingInterval() {
rescheduleReadHandler.rescheduleRead();
}
View on GitHub (pinned to 820761864e)
Solutions
- Set keySharedMode explicitly to AUTO_SPLIT or STICKY in the subscription's KeySharedMeta.
- Upgrade the broker to a version whose KeySharedMode enum includes the value the client is sending (check protocol/proto compatibility between client and broker versions).
- Inspect the actual subscribe payload (proxy logs / client debug) to confirm which numeric enum value is being sent; fix whichever component leaves it UNSET.
Example fix
// before
KeySharedMeta ksm = new KeySharedMeta();
// keySharedMode left UNSET -> Invalid key-shared mode: UNSET
// after
KeySharedMeta ksm = new KeySharedMeta()
.setKeySharedMode(KeySharedMode.AUTO_SPLIT); Defensive patterns
Strategy: validation
Validate before calling
static void requireSupportedKeySharedMode(KeySharedMeta ksm) {
var mode = ksm.getKeySharedMode();
if (mode != KeySharedMode.AUTO_SPLIT && mode != KeySharedMode.STICKY) {
throw new IllegalArgumentException(
"keySharedMode must be AUTO_SPLIT or STICKY, got: " + mode);
}
}
// call before building/serializing the subscribe command Type guard
static boolean isSupportedKeySharedMode(KeySharedMeta ksm) {
return ksm.getKeySharedMode() == KeySharedMode.AUTO_SPLIT
|| ksm.getKeySharedMode() == KeySharedMode.STICKY;
} Try / catch
try {
subscribe(ksm);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Invalid key-shared mode")) {
log.warn("Unsupported KeySharedMode from client; resubscribing with AUTO_SPLIT");
subscribe(ksm.setKeySharedMode(KeySharedMode.AUTO_SPLIT));
} else throw e;
} Prevention
- Always set keySharedMode explicitly; never rely on the proto default/UNSET.
- Keep client and broker protocol versions aligned; check KeySharedMode enum compatibility before upgrading clients ahead of brokers.
- Log the raw KeySharedMode in client debug output to catch UNSET early in tests.
When it happens
Trigger: Subscribing with KeySharedMeta whose keySharedMode field is unset or set to a proto enum value the broker's KeySharedMode doesn't map to (e.g. a value added in a newer client/protocol version than the broker understands, or UNSET); deserialization producing a mode outside {AUTO_SPLIT, STICKY}.
Common situations: Newer client SDK sending a newly introduced KeySharedMode enum value to an older broker; hand-constructed subscribe commands where keySharedMode was never set (UNSET); proxy or third-party tooling rewriting KeySharedMeta and corrupting the enum; cross-version upgrades where broker lags client protocol.
Related errors
- Entry-bucket subscription must declare the segment's bucket
- Entry-bucket boundaries must be ascending, contiguous and st
- Entry-bucket boundaries must tile the 16-bit ring: last rang
- Entry-bucket 0 must span at least [0,1] to hold the canonica
- Invalid key-shared mode: ${keySharedMode}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/d466886bf9595c04.
Report an issue: GitHub.