apache/pulsar · error · IllegalArgumentException
brokerCloseInactiveTopicsEnabled only supports brokerDeleteI
Error message
brokerCloseInactiveTopicsEnabled only supports brokerDeleteInactiveTopicsMode=delete_when_no_subscriptions. Under delete_when_subscriptions_caught_up a topic whose subscriptions are caught up is inactive even while consumers are still connected, so closing it would repeatedly unload and reload the topic.
What it means
This IllegalArgumentException is thrown at broker startup when brokerCloseInactiveTopicsEnabled is true but brokerDeleteInactiveTopicsMode is set to delete_when_subscriptions_caught_up. Topic inactivity detection under that mode marks a topic inactive when all subscriptions are caught up even while consumers remain connected, so closing such topics would unload and reload them in a loop. The broker rejects the combination at startup instead of allowing the churn.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java:915
&& config.getBacklogQuotaDefaultLimitSecond() > 0
&& config.getBacklogQuotaDefaultLimitSecond() >= config.getDefaultRetentionTimeInMinutes() * 60) {
throw new IllegalArgumentException(String.format("The retention time must > the backlog quota limit "
+ "time, but the configured backlog quota limit time duration is %d, "
+ "the retention time duration is %d",
config.getBacklogQuotaDefaultLimitSecond(),
config.getDefaultRetentionTimeInMinutes() * 60));
}
if (config.isBrokerDeleteInactiveTopicsEnabled() && config.isBrokerCloseInactiveTopicsEnabled()) {
throw new IllegalArgumentException(
"brokerDeleteInactiveTopicsEnabled and brokerCloseInactiveTopicsEnabled are mutually "
+ "exclusive. Enable at most one of them.");
}
if (config.isBrokerCloseInactiveTopicsEnabled()
&& config.getBrokerDeleteInactiveTopicsMode()
!= InactiveTopicDeleteMode.delete_when_no_subscriptions) {
throw new IllegalArgumentException(
"brokerCloseInactiveTopicsEnabled only supports brokerDeleteInactiveTopicsMode="
+ "delete_when_no_subscriptions. Under delete_when_subscriptions_caught_up a topic "
+ "whose subscriptions are caught up is inactive even while consumers are still "
+ "connected, so closing it would repeatedly unload and reload the topic.");
}
openTelemetryTopicStats = new OpenTelemetryTopicStats(this);
openTelemetryConsumerStats = new OpenTelemetryConsumerStats(this);
openTelemetryProducerStats = new OpenTelemetryProducerStats(this);
openTelemetryReplicatorStats = new OpenTelemetryReplicatorStats(this);
openTelemetryReplicatedSubscriptionStats = new OpenTelemetryReplicatedSubscriptionStats(this);
localMetadataSynchronizer = StringUtils.isNotBlank(config.getMetadataSyncEventTopic())
? new PulsarMetadataEventSynchronizer(this, config.getMetadataSyncEventTopic())
: null;
localMetadataStore = createLocalMetadataStore(localMetadataSynchronizer,
openTelemetry.getOpenTelemetryService().getOpenTelemetry());
localMetadataStore.registerSessionListener(this::handleMetadataSessionEvent);View on GitHub (pinned to 820761864e)
Solutions
- Set brokerDeleteInactiveTopicsMode=delete_when_no_subscriptions when brokerCloseInactiveTopicsEnabled=true (delete_when_no_subscriptions is that flag's only supported mode).
- If you need delete_when_subscriptions_caught_up semantics, set brokerCloseInactiveTopicsEnabled=false and rely on deletion instead.
- Review both flags together in broker.conf / env overrides before deploying; they are coupled by this validation.
- Restart the broker and verify startup completes.
Example fix
// before (broker.conf) brokerCloseInactiveTopicsEnabled=true brokerDeleteInactiveTopicsMode=delete_when_subscriptions_caught_up // after brokerCloseInactiveTopicsEnabled=true brokerDeleteInactiveTopicsMode=delete_when_no_subscriptions
Defensive patterns
Strategy: validation
Validate before calling
// before broker start (Java)
if (conf.isBrokerCloseInactiveTopicsEnabled()
&& conf.getBrokerDeleteInactiveTopicsMode() != InactiveTopicDeleteMode.delete_when_no_subscriptions) {
throw new IllegalArgumentException(
"brokerCloseInactiveTopicsEnabled requires brokerDeleteInactiveTopicsMode=delete_when_no_subscriptions");
} Try / catch
try {
pulsar.start();
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("brokerCloseInactiveTopicsEnabled only supports")) {
// fix broker.conf: set mode to delete_when_no_subscriptions or disable close-inactive-topics, then retry
} else {
throw e;
}
} Prevention
- Whenever enabling brokerCloseInactiveTopicsEnabled, also pin brokerDeleteInactiveTopicsMode=delete_when_no_subscriptions.
- Treat the mode and the close flag as one coupled setting in config templates.
- Add the flag/mode pairing to config CI checks.
- If deletion needs delete_when_subscriptions_caught_up, disable closing instead of mixing.
When it happens
Trigger: Starting a broker with isBrokerCloseInactiveTopicsEnabled()==true and getBrokerDeleteInactiveTopicsMode() != delete_when_no_subscriptions, i.e. the mode is delete_when_subscriptions_caught_up (or all Kafka-style modes) — e.g. by only changing brokerDeleteInactiveTopicsMode from its default without disabling close-inactive-topics.
Common situations: Operators tune delete mode to delete_when_subscriptions_caught_up for safer deletion semantics while the close-inactive-topics feature is also on; inherited configs where the mode was changed for the delete feature but the close flag predates the constraint.
Related errors
- brokerDeleteInactiveTopicsEnabled and brokerCloseInactiveTop
- webServicePort/webServicePortTls or http/https bindAddresses
- The retention size must > the backlog quota limit size, but
- The retention time must > the backlog quota limit time, but
- No protocol handler is found for protocol `${protocol}`. Ava
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/4045368cb6dd728d.
Report an issue: GitHub.