{"record":{"id":"89a6c0535fc0551c","repo":"apache/pulsar","slug":"maxconsumerspersubscription-must-be-0-or-more","errorCode":null,"errorMessage":"maxConsumersPerSubscription must be 0 or more","messagePattern":"maxConsumersPerSubscription must be 0 or more","errorType":"validation","errorClass":"RestException","httpStatus":412,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java","lineNumber":2518,"sourceCode":"\n        } catch (RestException pfe) {\n            throw pfe;\n        } catch (Exception e) {\n            log.error()\n                    .attr(\"namespace\", namespaceName)\n                    .exception(e)\n                    .log(\"Failed to update maxConsumersPerTopic configuration for namespace\");\n            throw new RestException(e);\n        }\n    }\n\n    protected void internalSetMaxConsumersPerSubscription(Integer maxConsumersPerSubscription) {\n        validateNamespacePolicyOperation(namespaceName, PolicyName.MAX_CONSUMERS, PolicyOperation.WRITE);\n        validatePoliciesReadOnlyAccess();\n\n        try {\n            if (maxConsumersPerSubscription != null && maxConsumersPerSubscription < 0) {\n                throw new RestException(Status.PRECONDITION_FAILED,\n                        \"maxConsumersPerSubscription must be 0 or more\");\n            }\n            updatePolicies(namespaceName, policies -> {\n                policies.max_consumers_per_subscription = maxConsumersPerSubscription;\n                return policies;\n            });\n            log.info()\n                    .attr(\"namespace\", namespaceName)\n                    .attr(\"maxConsumersPerSubscription\", maxConsumersPerSubscription)\n                    .log(\"Successfully updated maxConsumersPerSubscription configuration\");\n        } catch (RestException pfe) {\n            throw pfe;\n        } catch (Exception e) {\n            log.error()\n                    .attr(\"namespace\", namespaceName)\n                    .exception(e)\n                    .log(\"Failed to update maxConsumersPerSubscription configuration\");\n            throw new RestException(e);","sourceCodeStart":2500,"sourceCodeEnd":2536,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java#L2500-L2536","documentation":"Thrown by internalSetMaxConsumersPerSubscription when the provided value is negative. The per-subscription consumer limit must be null (unset) or >= 0. The broker rejects the change with HTTP 412 PRECONDITION_FAILED before persisting the policy.","triggerScenarios":"POST /namespaces/{ns}/maxConsumersPerSubscription with a negative integer; using -1 intending 'unlimited' rather than null; config pipelines substituting an empty value with a negative default.","commonSituations":"Same sentinel confusion as other count-based policies (-1 = unlimited from other ecosystems); generated policy JSON with invalid defaults; manual typos in CLI invocations.","solutions":["Pass 0 or a positive integer","Use null/omit to clear the limit","Add a guard (value == null || value >= 0) in tooling that calls this endpoint"],"exampleFix":"// before\nadmin.namespaces().setMaxConsumersPerSubscription(\"my-tenant/my-ns\", -1); // 412\n// after\nadmin.namespaces().setMaxConsumersPerSubscription(\"my-tenant/my-ns\", null); // unset\nadmin.namespaces().setMaxConsumersPerSubscription(\"my-tenant/my-ns\", 10);","handlingStrategy":"validation","validationCode":"if (maxConsumersPerSubscription != null && maxConsumersPerSubscription < 0) {\n    throw new IllegalArgumentException(\"maxConsumersPerSubscription must be >= 0 or null\");\n}","typeGuard":"boolean isValidCount(Integer v) { return v == null || v >= 0; }","tryCatchPattern":"try {\n    admin.namespaces().setMaxConsumersPerSubscription(ns, maxConsumersPerSubscription);\n} catch (PulsarAdminException.PreconditionFailedException e) {\n    log.error(\"Negative maxConsumersPerSubscription rejected: use null for unlimited\");\n    throw e;\n}","preventionTips":["Use null to express unlimited","Convert -1 sentinels at config ingestion time","Add client-side range checks for all count-based policy setters"],"tags":["http-412","consumers","subscription","validation","admin-api"],"backgroundTag":"invalid-policy-value","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"}