{"record":{"id":"5383221a61fc8271","repo":"apache/pulsar","slug":"invalid-backlog-quota-type-s-valid-options-are-538322","errorCode":null,"errorMessage":"Invalid backlog quota type '%s'. Valid options are: %s","messagePattern":"Invalid backlog quota type '(.+?)'\\. Valid options are: (.+?)","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdTopicPolicies.java","lineNumber":1061,"sourceCode":"        @Option(names = { \"--global\", \"-g\" }, description = \"Whether to set this policy globally. \"\n                + \"If set to true, the policy will be replicate to other clusters asynchronously\")\n        private boolean isGlobal = false;\n\n        @Override\n        void run() throws PulsarAdminException {\n            BacklogQuota.RetentionPolicy policy;\n            BacklogQuota.BacklogQuotaType backlogQuotaType;\n\n            try {\n                policy = BacklogQuota.RetentionPolicy.valueOf(policyStr);\n            } 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            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            String persistentTopic = validatePersistentTopic(topicName);\n            BacklogQuota.Builder builder = BacklogQuota.builder().retentionPolicy(policy);\n\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            }","sourceCodeStart":1043,"sourceCodeEnd":1079,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdTopicPolicies.java#L1043-L1079","documentation":"pulsar-admin's set-backlog-quota topic policy command parses the --quota-type (or backlogQuotaType) argument with BacklogQuota.BacklogQuotaType.valueOf(). When the supplied string does not match an enum constant exactly, the IllegalArgumentException is rethrown as a JCommander ParameterException listing the valid options. It is pure client-side argument validation before any request reaches the broker.","triggerScenarios":"Running 'pulsar-admin topics set-backlog-quota <topic> --quota-type <bad-value>' where <bad-value> is misspelled, wrong-cased (e.g. 'Destination_Storage' or 'destination-storage'), or a value valid in a different enum (e.g. retention policy names like 'producer_exception').","commonSituations":"Copy-pasting examples from older documentation or other systems (Kafka/Disk-usage quota names); scripts written before the 'message_age' type was introduced; shell scripts with a typo or camelCase vs snake_case confusion; passing a retention policy name in the quota-type slot.","solutions":["Use one of the exact enum constants printed in the error message: destination_storage or message_age","Check the enum constants with: org.apache.pulsar.common.policies.data.BacklogQuota.BacklogQuotaType","For size-based limits use 'destination_storage' with --limit; for time-based use 'message_age' with --limitTime"],"exampleFix":"// before\npulsar-admin topics set-backlog-quota my-topic --quota-type DestinationStorage --limit 10G\n// after\npulsar-admin topics set-backlog-quota my-topic --quota-type destination_storage --limit 10G","handlingStrategy":"validation","validationCode":"final Set<String> VALID = Arrays.stream(BacklogQuota.BacklogQuotaType.values()).map(Enum::name).collect(Collectors.toSet());\nif (!VALID.contains(quotaType)) throw new IllegalArgumentException(\"quotaType must be one of \" + VALID + \", got: \" + quotaType);","typeGuard":"static boolean isValidBacklogQuotaType(String s) {\n    return Arrays.stream(BacklogQuota.BacklogQuotaType.values()).anyMatch(t -> t.name().equals(s));\n}","tryCatchPattern":null,"preventionTips":["Use tab-completion or --help to list valid quota types before invoking","Keep quota type strings in a constants file shared by scripts","Remember names are exact snake_case enum constants, case-sensitive"],"tags":["cli","pulsar-admin","argument-validation","enum"],"backgroundTag":"invalid-enum-value","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"}