{"record":{"id":"1b3960878c0b3267","repo":"apache/pulsar","slug":"quota-type-of-destination-storage-needs-a-size-l","errorCode":null,"errorMessage":"Quota type of 'destination_storage' needs a size limit","messagePattern":"Quota type of 'destination_storage' needs a size limit","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java","lineNumber":1325,"sourceCode":"            } catch (IllegalArgumentException e) {\n                throw new ParameterException(String.format(\"Invalid retention policy type '%s'. Valid options are: %s\",\n                        policyStr, Arrays.toString(BacklogQuota.RetentionPolicy.values())));\n            }\n\n            try {\n                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","sourceCodeStart":1307,"sourceCodeEnd":1343,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java#L1307-L1343","documentation":"When the backlog quota type is destination_storage, the quota is defined by a storage size, so --limit-size is mandatory. The CLI throws this ParameterException if limit is null, because a destination_storage quota without a size would be meaningless.","triggerScenarios":"Running `pulsar-admin namespaces set-backlog-quota <ns> --backlog-quota-type destination_storage --retention-policy <policy>` without --limit-size (limit == null), or with a time flag only.","commonSituations":"Users copying the message_age example but switching the type to destination_storage; automation where --limit-size is only appended for one quota type branch; forgetting the flag when converting from time-based to size-based quotas.","solutions":["Add --limit-size (e.g. --limit-size 10G) to the command","Or, if you meant a time-based quota, change --backlog-quota-type to message_age and pass --limit-time instead"],"exampleFix":"// before\npulsar-admin namespaces set-backlog-quota my-tenant/my-ns --backlog-quota-type destination_storage --retention-policy producer_exception\n// after\npulsar-admin namespaces set-backlog-quota my-tenant/my-ns --backlog-quota-type destination_storage --retention-policy producer_exception --limit-size 10G","handlingStrategy":"validation","validationCode":"// shell guard\nif [ \"$QUOTA_TYPE\" = \"destination_storage\" ] && [ -z \"$LIMIT_SIZE\" ]; then\n  echo \"--limit-size required for destination_storage\" >&2; exit 1;\nfi","typeGuard":"// pseudo: pair type with its required limit\nif (\"destination_storage\".equals(type) && limitSize == null) {\n    throw new IllegalArgumentException(\"--limit-size required for destination_storage\");\n}","tryCatchPattern":"try {\n    admin.namespaces().setBacklogQuota(ns, quota, type);\n} catch (IllegalArgumentException e) {\n    // re-issue the command with --limit-size\n}","preventionTips":["Pair destination_storage always with --limit-size","Pair message_age always with --limit-time","Build wrapper functions that enforce the pairing"],"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-14T00:17:10.932Z"}