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

  1. Set brokerDeleteInactiveTopicsMode=delete_when_no_subscriptions when brokerCloseInactiveTopicsEnabled=true (delete_when_no_subscriptions is that flag's only supported mode).
  2. If you need delete_when_subscriptions_caught_up semantics, set brokerCloseInactiveTopicsEnabled=false and rely on deletion instead.
  3. Review both flags together in broker.conf / env overrides before deploying; they are coupled by this validation.
  4. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/4045368cb6dd728d. Report an issue: GitHub.