apache/pulsar · error · ParameterException

Invalid backlog quota type '%s'. Valid options are: %s

Error message

Invalid backlog quota type '%s'. Valid options are: %s

What it means

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.

Source

Thrown at pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdTopicPolicies.java:1061

        @Option(names = { "--global", "-g" }, description = "Whether to set this policy globally. "
                + "If set to true, the policy will be replicate to other clusters asynchronously")
        private boolean isGlobal = false;

        @Override
        void run() throws PulsarAdminException {
            BacklogQuota.RetentionPolicy policy;
            BacklogQuota.BacklogQuotaType backlogQuotaType;

            try {
                policy = BacklogQuota.RetentionPolicy.valueOf(policyStr);
            } catch (IllegalArgumentException e) {
                throw new ParameterException(String.format("Invalid retention policy type '%s'. Valid options are: %s",
                        policyStr, Arrays.toString(BacklogQuota.RetentionPolicy.values())));
            }
            try {
                backlogQuotaType = BacklogQuota.BacklogQuotaType.valueOf(backlogQuotaTypeStr);
            } catch (IllegalArgumentException e) {
                throw new ParameterException(String.format("Invalid backlog quota type '%s'. Valid options are: %s",
                        backlogQuotaTypeStr, Arrays.toString(BacklogQuota.BacklogQuotaType.values())));
            }
            String persistentTopic = validatePersistentTopic(topicName);
            BacklogQuota.Builder builder = BacklogQuota.builder().retentionPolicy(policy);

            if (backlogQuotaType == BacklogQuota.BacklogQuotaType.destination_storage) {
                // set quota by storage size
                if (limit == null) {
                    throw new ParameterException("Quota type of 'destination_storage' needs a size limit");
                }
                builder.limitSize(limit);
            } else {
                // set quota by time
                if (limitTimeInSec == null) {
                    throw new ParameterException("Quota type of 'message_age' needs a time limit");
                }
                builder.limitTime(limitTimeInSec.intValue());
            }

View on GitHub (pinned to 820761864e)

Solutions

  1. Use one of the exact enum constants printed in the error message: destination_storage or message_age
  2. Check the enum constants with: org.apache.pulsar.common.policies.data.BacklogQuota.BacklogQuotaType
  3. For size-based limits use 'destination_storage' with --limit; for time-based use 'message_age' with --limitTime

Example fix

// before
pulsar-admin topics set-backlog-quota my-topic --quota-type DestinationStorage --limit 10G
// after
pulsar-admin topics set-backlog-quota my-topic --quota-type destination_storage --limit 10G
Defensive patterns

Strategy: validation

Validate before calling

final Set<String> VALID = Arrays.stream(BacklogQuota.BacklogQuotaType.values()).map(Enum::name).collect(Collectors.toSet());
if (!VALID.contains(quotaType)) throw new IllegalArgumentException("quotaType must be one of " + VALID + ", got: " + quotaType);

Type guard

static boolean isValidBacklogQuotaType(String s) {
    return Arrays.stream(BacklogQuota.BacklogQuotaType.values()).anyMatch(t -> t.name().equals(s));
}

Prevention

When it happens

Trigger: 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').

Common situations: 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.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/5383221a61fc8271. Report an issue: GitHub.