{"record":{"id":"a62086d0c3e286ee","repo":"apache/pulsar","slug":"quota-type-of-message-age-needs-a-time-limit","errorCode":null,"errorMessage":"Quota type of 'message_age' needs a time limit","messagePattern":"Quota type of 'message_age' needs a time limit","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java","lineNumber":1331,"sourceCode":"                backlogQuotaType = BacklogQuota.BacklogQuotaType.valueOf(backlogQuotaTypeStr);\n            } catch (IllegalArgumentException e) {\n                throw new ParameterException(String.format(\"Invalid backlog quota type '%s'. Valid options are: %s\",\n                        backlogQuotaTypeStr, Arrays.toString(BacklogQuota.BacklogQuotaType.values())));\n            }\n\n            String namespace = validateNamespace(namespaceName);\n\n            BacklogQuota.Builder builder = BacklogQuota.builder().retentionPolicy(policy);\n            if (backlogQuotaType == BacklogQuota.BacklogQuotaType.destination_storage) {\n                // set quota by storage size\n                if (limit == null) {\n                    throw new ParameterException(\"Quota type of 'destination_storage' needs a size limit\");\n                }\n                builder.limitSize(limit);\n            } else {\n                // set quota by time\n                if (limitTimeInSec == null) {\n                    throw new ParameterException(\"Quota type of 'message_age' needs a time limit\");\n                }\n                builder.limitTime(limitTimeInSec.intValue());\n            }\n            getAdmin().namespaces().setBacklogQuota(namespace, builder.build(), backlogQuotaType);\n        }\n    }\n\n    @Command(description = \"Remove a backlog quota policy from a namespace\")\n    private class RemoveBacklogQuota extends CliCommand {\n        @Parameters(description = \"tenant/namespace\", arity = \"1\")\n        private String namespaceName;\n\n        @Option(names = {\"-t\", \"--type\"}, description = \"Backlog quota type to remove. Valid options are: \"\n                + \"destination_storage, message_age\")\n        private String backlogQuotaTypeStr = BacklogQuota.BacklogQuotaType.destination_storage.name();\n\n        @Override\n        void run() throws PulsarAdminException {","sourceCodeStart":1313,"sourceCodeEnd":1349,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java#L1313-L1349","documentation":"When the backlog quota type is message_age, the quota is defined by a time limit, so --limit-time is mandatory. The CLI throws this ParameterException when limitTimeInSec is null, since a message_age quota without a time limit is invalid.","triggerScenarios":"Running `pulsar-admin namespaces set-backlog-quota <ns> --backlog-quota-type message_age --retention-policy <policy>` without --limit-time (limitTimeInSec == null), or passing only --limit-size.","commonSituations":"Users copying the destination_storage example but switching the type to message_age; scripts that always set --limit-size regardless of quota type; forgetting to convert hours/minutes to seconds.","solutions":["Add --limit-time <seconds> to the command","Or, if you meant a size quota, use --backlog-quota-type destination_storage with --limit-size"],"exampleFix":"// before\npulsar-admin namespaces set-backlog-quota my-tenant/my-ns --backlog-quota-type message_age --retention-policy consumer_backlog_eviction --limit-size 1G\n// after\npulsar-admin namespaces set-backlog-quota my-tenant/my-ns --backlog-quota-type message_age --retention-policy consumer_backlog_eviction --limit-time 3600","handlingStrategy":"validation","validationCode":"// shell guard\nif [ \"$QUOTA_TYPE\" = \"message_age\" ] && [ -z \"$LIMIT_TIME\" ]; then\n  echo \"--limit-time required for message_age\" >&2; exit 1;\nfi","typeGuard":"// pseudo: pair type with its required limit\nif (\"message_age\".equals(type) && limitTimeInSec == null) {\n    throw new IllegalArgumentException(\"--limit-time required for message_age\");\n}","tryCatchPattern":"try {\n    admin.namespaces().setBacklogQuota(ns, quota, type);\n} catch (IllegalArgumentException e) {\n    // re-issue the command with --limit-time in seconds\n}","preventionTips":["Convert durations to seconds before passing --limit-time","Pair message_age with --limit-time, destination_storage with --limit-size","Add assertions in scripts linking quota type to its limit flag"],"tags":["cli","parameter-validation","backlog-quota","pulsar-admin"],"backgroundTag":"missing-required-cli-argument","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}