apache/pulsar · error · RestException
maxConsumersPerTopic must be 0 or more
Error message
maxConsumersPerTopic must be 0 or more
What it means
Thrown by internalSetMaxConsumersPerTopic when the supplied value is negative. The limit is a consumer count per topic and must be null (unset) or >= 0. The update is rejected with HTTP 412 PRECONDITION_FAILED before any policy change.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java:2490
.exception(e)
.log("Failed to update maxProducersPerTopic configuration for namespace");
throw new RestException(e);
}
}
protected CompletableFuture<Boolean> internalGetDeduplicationAsync() {
return validateNamespacePolicyOperationAsync(namespaceName, PolicyName.DEDUPLICATION, PolicyOperation.READ)
.thenCompose(__ -> getNamespacePoliciesAsync(namespaceName))
.thenApply(policies -> policies.deduplicationEnabled);
}
protected void internalSetMaxConsumersPerTopic(Integer maxConsumersPerTopic) {
validateNamespacePolicyOperation(namespaceName, PolicyName.MAX_CONSUMERS, PolicyOperation.WRITE);
validatePoliciesReadOnlyAccess();
try {
if (maxConsumersPerTopic != null && maxConsumersPerTopic < 0) {
throw new RestException(Status.PRECONDITION_FAILED, "maxConsumersPerTopic must be 0 or more");
}
updatePolicies(namespaceName, policies -> {
policies.max_consumers_per_topic = maxConsumersPerTopic;
return policies;
});
log.info()
.attr("namespace", namespaceName)
.attr("maxConsumersPerTopic", maxConsumersPerTopic)
.log("Successfully updated maxConsumersPerTopic configuration");
} catch (RestException pfe) {
throw pfe;
} catch (Exception e) {
log.error()
.attr("namespace", namespaceName)
.exception(e)
.log("Failed to update maxConsumersPerTopic configuration for namespace");
throw new RestException(e);View on GitHub (pinned to 820761864e)
Solutions
- Pass 0 or a positive integer
- Use null (omit the parameter) to unset the limit
- Validate the input client-side before calling the admin API
Example fix
// before
admin.namespaces().setMaxConsumersPerTopic("my-tenant/my-ns", -1); // 412
// after
admin.namespaces().setMaxConsumersPerTopic("my-tenant/my-ns", null); // unset
admin.namespaces().setMaxConsumersPerTopic("my-tenant/my-ns", 50); Defensive patterns
Strategy: validation
Validate before calling
if (maxConsumersPerTopic != null && maxConsumersPerTopic < 0) {
throw new IllegalArgumentException("maxConsumersPerTopic must be >= 0 or null");
} Type guard
boolean isValidCount(Integer v) { return v == null || v >= 0; } Try / catch
try {
admin.namespaces().setMaxConsumersPerTopic(ns, maxConsumersPerTopic);
} catch (PulsarAdminException.PreconditionFailedException e) {
log.error("Negative maxConsumersPerTopic rejected: use null for unlimited");
throw e;
} Prevention
- Use null to unset limits
- Translate -1 sentinels from other systems to null at config boundaries
- Validate before API calls in automation
When it happens
Trigger: POST /namespaces/{ns}/maxConsumersPerTopic with a negative integer; passing -1 as an attempted 'unlimited' sentinel; automated policy generators emitting negative defaults.
Common situations: Scripts assuming -1 means unlimited; typos in numeric config; ported configs from other middleware where -1 is the conventional unlimited marker.
Related errors
- maxConsumersPerSubscription must be 0 or more
- Topic name is not valid
- Partitioned Topic Name should not contain '-partition-'
- Subscription has active connected consumers
- Invalid value for message TTL
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a37374efbfe10b0a.
Report an issue: GitHub.