apache/pulsar · error · IllegalArgumentException

The retention time must > the backlog quota limit time, but

Error message

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

What it means

This IllegalArgumentException is thrown at broker startup when the default backlog quota time limit is greater than or equal to the default retention time. Retention time must be strictly longer than the backlog quota time limit; otherwise a topic hitting the quota would be stopped before retention ever had a chance to enforce its time-based deletion. The check runs in PulsarService.start() against backlogQuotaDefaultLimitSecond and defaultRetentionTimeInMinutes * 60.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java:899

            if (config.isAuthorizationEnabled() && !config.isAuthenticationEnabled()) {
                throw new IllegalStateException("Invalid broker configuration. Authentication must be enabled with "
                        + "authenticationEnabled=true when authorization is enabled with authorizationEnabled=true.");
            }

            if (config.getDefaultRetentionSizeInMB() > 0
                    && config.getBacklogQuotaDefaultLimitBytes() > 0
                    && config.getBacklogQuotaDefaultLimitBytes()
                    >= (config.getDefaultRetentionSizeInMB() * 1024L * 1024L)) {
                throw new IllegalArgumentException(String.format("The retention size must > the backlog quota limit "
                                + "size, but the configured backlog quota limit bytes is %d, the retention size is %d",
                        config.getBacklogQuotaDefaultLimitBytes(),
                        config.getDefaultRetentionSizeInMB() * 1024L * 1024L));
            }

            if (config.getDefaultRetentionTimeInMinutes() > 0
                    && 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 "

View on GitHub (pinned to 820761864e)

Solutions

  1. Increase defaultRetentionTimeInMinutes (or lower backlogQuotaDefaultLimitSecond) so retention time in seconds is strictly greater than the backlog quota time limit.
  2. Set backlogQuotaDefaultLimitSecond to -1 (disabled) to skip time-based quota enforcement and the check.
  3. Set defaultRetentionTimeInMinutes to -1 (disabled) if retention should not be time-based.
  4. Recompute units carefully: the comparison converts retention minutes to seconds; a value that looks safe in minutes may not be.

Example fix

// before (broker.conf)
defaultRetentionTimeInMinutes=30
backlogQuotaDefaultLimitSecond=3600
// after
defaultRetentionTimeInMinutes=120
backlogQuotaDefaultLimitSecond=3600
Defensive patterns

Strategy: validation

Validate before calling

// before broker start (Java)
if (conf.getDefaultRetentionTimeInMinutes() > 0 && conf.getBacklogQuotaDefaultLimitSecond() > 0
        && conf.getBacklogQuotaDefaultLimitSecond() >= conf.getDefaultRetentionTimeInMinutes() * 60) {
    throw new IllegalArgumentException(
        "backlogQuotaDefaultLimitSecond must be < defaultRetentionTimeInMinutes * 60 (or disabled)");
}

Try / catch

try {
    pulsar.start();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("retention time must > the backlog quota limit")) {
        // fix broker.conf: raise retention time or lower/disable backlogQuotaDefaultLimitSecond, then retry
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Starting a broker with defaultRetentionTimeInMinutes > 0, backlogQuotaDefaultLimitSecond > 0, and backlogQuotaDefaultLimitSecond >= defaultRetentionTimeInMinutes * 60 (e.g. retention 30 minutes vs backlog quota limit 1 hour = 3600s).

Common situations: Operators raise the backlog quota time limit (e.g. to tolerate slow consumers) without noticing it now exceeds the retention duration, causing the broker to fail startup validation.

Related errors


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