{"record":{"id":"a8312c6add60a758","repo":"apache/pulsar","slug":"the-attribute-policy-cannot-be-null","errorCode":null,"errorMessage":"the attribute policy cannot be null","messagePattern":"the attribute policy cannot be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/BacklogQuota.java","lineNumber":94,"sourceCode":"    }\n\n    /**\n     * Enumeration type determines how to retain backlog against the resource shortages.\n     */\n    enum RetentionPolicy {\n        /** Policy which holds producer's send request until the resource becomes available (or holding times out). */\n        producer_request_hold,\n\n        /** Policy which throws javax.jms.ResourceAllocationException to the producer. */\n        producer_exception,\n\n        /** Policy which evicts the oldest message from the slowest consumer's backlog. */\n        consumer_backlog_eviction,\n    }\n\n    default void validate() {\n        if (getPolicy() == null) {\n            throw new IllegalArgumentException(\"the attribute policy cannot be null\");\n        }\n    }\n}\n","sourceCodeStart":76,"sourceCodeEnd":98,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/BacklogQuota.java#L76-L98","documentation":"BacklogQuota.validate() (called when setting a backlog quota via the admin API, e.g. setBacklogQuotaAsync) throws IllegalArgumentException if the quota's policy field is null. A BacklogQuota without a policy is considered invalid because the broker must know how to enforce the quota.","triggerScenarios":"Calling namespacePolicies().setBacklogQuotaAsync(...) (or builder paths) with a BacklogQuota built without setting policy — e.g. BacklogQuotaImpl.builder().limitSize(...).build() omitting policy.","commonSituations":"Programmatically constructing BacklogQuota from deserialized partial data (missing policy in JSON), copying config where the policy key was omitted, default-constructed quota objects passed directly to the admin API.","solutions":["Set the policy explicitly: builder().policy(RetentionPolicy.consumer_backlog_eviction)...build()","Validate quota.getPolicy() != null before calling setBacklogQuotaAsync","Check the source JSON/config that the policy field is present and correctly named"],"exampleFix":"// before\nBacklogQuota quota = BacklogQuotaImpl.builder().limitSize(1_000_000_000L).build();\nadmin.namespaces().setBacklogQuotaAsync(ns, quota);\n// after\nBacklogQuota quota = BacklogQuotaImpl.builder()\n    .limitSize(1_000_000_000L)\n    .policy(RetentionPolicy.consumer_backlog_eviction)\n    .build();\nadmin.namespaces().setBacklogQuotaAsync(ns, quota);","handlingStrategy":"validation","validationCode":"if (quota.getPolicy() == null) {\n    throw new IllegalArgumentException(\"backlog quota policy must be set before submitting\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    admin.namespaces().setBacklogQuotaAsync(ns, quota).get();\n} catch (ExecutionException e) {\n    if (e.getCause() instanceof IllegalArgumentException) { /* fix quota policy */ }\n}","preventionTips":["Always use BacklogQuotaImpl.builder() and set policy explicitly","Validate deserialized quota objects before sending to admin API","Check JSON configs include the policy field"],"tags":["validation","illegal-argument","configuration"],"backgroundTag":"required-field-missing","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"}