{"record":{"id":"5a9d500cb4d2f1cc","repo":"apache/pulsar","slug":"the-retention-time-must-the-backlog-quota-limit","errorCode":null,"errorMessage":"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","messagePattern":"The retention time must > the backlog quota limit time, but the configured backlog quota limit time duration is (.+?), the retention time duration is (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java","lineNumber":899,"sourceCode":"            if (config.isAuthorizationEnabled() && !config.isAuthenticationEnabled()) {\n                throw new IllegalStateException(\"Invalid broker configuration. Authentication must be enabled with \"\n                        + \"authenticationEnabled=true when authorization is enabled with authorizationEnabled=true.\");\n            }\n\n            if (config.getDefaultRetentionSizeInMB() > 0\n                    && config.getBacklogQuotaDefaultLimitBytes() > 0\n                    && config.getBacklogQuotaDefaultLimitBytes()\n                    >= (config.getDefaultRetentionSizeInMB() * 1024L * 1024L)) {\n                throw new IllegalArgumentException(String.format(\"The retention size must > the backlog quota limit \"\n                                + \"size, but the configured backlog quota limit bytes is %d, the retention size is %d\",\n                        config.getBacklogQuotaDefaultLimitBytes(),\n                        config.getDefaultRetentionSizeInMB() * 1024L * 1024L));\n            }\n\n            if (config.getDefaultRetentionTimeInMinutes() > 0\n                    && config.getBacklogQuotaDefaultLimitSecond() > 0\n                    && config.getBacklogQuotaDefaultLimitSecond() >= config.getDefaultRetentionTimeInMinutes() * 60) {\n                throw new IllegalArgumentException(String.format(\"The retention time must > the backlog quota limit \"\n                                + \"time, but the configured backlog quota limit time duration is %d, \"\n                                + \"the retention time duration is %d\",\n                        config.getBacklogQuotaDefaultLimitSecond(),\n                        config.getDefaultRetentionTimeInMinutes() * 60));\n            }\n\n            if (config.isBrokerDeleteInactiveTopicsEnabled() && config.isBrokerCloseInactiveTopicsEnabled()) {\n                throw new IllegalArgumentException(\n                        \"brokerDeleteInactiveTopicsEnabled and brokerCloseInactiveTopicsEnabled are mutually \"\n                                + \"exclusive. Enable at most one of them.\");\n            }\n\n            if (config.isBrokerCloseInactiveTopicsEnabled()\n                    && config.getBrokerDeleteInactiveTopicsMode()\n                            != InactiveTopicDeleteMode.delete_when_no_subscriptions) {\n                throw new IllegalArgumentException(\n                        \"brokerCloseInactiveTopicsEnabled only supports brokerDeleteInactiveTopicsMode=\"\n                                + \"delete_when_no_subscriptions. Under delete_when_subscriptions_caught_up a topic \"","sourceCodeStart":881,"sourceCodeEnd":917,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java#L881-L917","documentation":"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.","triggerScenarios":"Starting a broker with defaultRetentionTimeInMinutes > 0, backlogQuotaDefaultLimitSecond > 0, and backlogQuotaDefaultLimitSecond >= defaultRetentionTimeInMinutes * 60 (e.g. retention 30 minutes vs backlog quota limit 1 hour = 3600s).","commonSituations":"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.","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."],"exampleFix":"// before (broker.conf)\ndefaultRetentionTimeInMinutes=30\nbacklogQuotaDefaultLimitSecond=3600\n// after\ndefaultRetentionTimeInMinutes=120\nbacklogQuotaDefaultLimitSecond=3600","handlingStrategy":"validation","validationCode":"// before broker start (Java)\nif (conf.getDefaultRetentionTimeInMinutes() > 0 && conf.getBacklogQuotaDefaultLimitSecond() > 0\n        && conf.getBacklogQuotaDefaultLimitSecond() >= conf.getDefaultRetentionTimeInMinutes() * 60) {\n    throw new IllegalArgumentException(\n        \"backlogQuotaDefaultLimitSecond must be < defaultRetentionTimeInMinutes * 60 (or disabled)\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    pulsar.start();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"retention time must > the backlog quota limit\")) {\n        // fix broker.conf: raise retention time or lower/disable backlogQuotaDefaultLimitSecond, then retry\n    } else {\n        throw e;\n    }\n}","preventionTips":["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."],"tags":["broker","configuration","startup","backlog-quota","retention"],"backgroundTag":"invalid-configuration","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}