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
- Increase defaultRetentionTimeInMinutes (or lower backlogQuotaDefaultLimitSecond) so retention time in seconds is strictly greater than the backlog quota time limit.
- Set backlogQuotaDefaultLimitSecond to -1 (disabled) to skip time-based quota enforcement and the check.
- Set defaultRetentionTimeInMinutes to -1 (disabled) if retention should not be time-based.
- 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
- Compare in a single unit (seconds) when tuning: retention seconds must exceed backlog quota seconds.
- Convert minutes to seconds explicitly in dashboards/scripts to avoid unit confusion.
- Add the time comparison to config CI checks before rollout.
- Disable one limit (-1) if you only want time-based quota or time-based retention.
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
- The retention size must > the backlog quota limit size, but
- webServicePort/webServicePortTls or http/https bindAddresses
- brokerDeleteInactiveTopicsEnabled and brokerCloseInactiveTop
- brokerCloseInactiveTopicsEnabled only supports brokerDeleteI
- No protocol handler is found for protocol `${protocol}`. Ava
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/5a9d500cb4d2f1cc.
Report an issue: GitHub.