{"record":{"id":"c018fad6d20cf8a4","repo":"apache/rocketmq","slug":"the-actions-is-empty","errorCode":null,"errorMessage":"The actions is empty.","messagePattern":"The actions is empty\\.","errorType":"validation","errorClass":"AuthorizationException","httpStatus":null,"severity":"error","filePath":"auth/src/main/java/org/apache/rocketmq/auth/authorization/manager/AuthorizationMetadataManagerImpl.java","lineNumber":250,"sourceCode":"        }\n        for (PolicyEntry policyEntry : policyEntries) {\n            this.validate(policyEntry);\n        }\n    }\n\n    private void validate(PolicyEntry entry) {\n        Resource resource = entry.getResource();\n        if (resource == null) {\n            throw new AuthorizationException(\"The resource is null.\");\n        }\n        if (resource.getResourceType() == null) {\n            throw new AuthorizationException(\"The resource type is null.\");\n        }\n        if (resource.getResourcePattern() == null) {\n            throw new AuthorizationException(\"The resource pattern is null.\");\n        }\n        if (CollectionUtils.isEmpty(entry.getActions())) {\n            throw new AuthorizationException(\"The actions is empty.\");\n        }\n        if (entry.getActions().contains(Action.ANY)) {\n            throw new AuthorizationException(\"The actions can not be Any.\");\n        }\n        Environment environment = entry.getEnvironment();\n        if (environment != null && CollectionUtils.isNotEmpty(environment.getSourceIps())) {\n            for (String sourceIp : environment.getSourceIps()) {\n                if (StringUtils.isBlank(sourceIp)) {\n                    throw new AuthorizationException(\"The source ip is empty.\");\n                }\n                if (!IPAddressUtils.isValidIPOrCidr(sourceIp)) {\n                    throw new AuthorizationException(\"The source ip is invalid.\");\n                }\n            }\n        }\n        if (entry.getDecision() == null) {\n            throw new AuthorizationException(\"The decision is null or illegal.\");\n        }","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/auth/src/main/java/org/apache/rocketmq/auth/authorization/manager/AuthorizationMetadataManagerImpl.java#L232-L268","documentation":"Thrown by AuthorizationMetadataManagerImpl.validate() when a PolicyEntry submitted through createAcl/updateAcl has a null or empty actions collection. Every ACL policy in RocketMQ's new auth model must explicitly declare which actions (PUB, SUB, or both) it grants or denies. The check runs before the policy is persisted, so nothing is written to the metadata store.","triggerScenarios":"Calling AuthorizationMetadataManager.createAcl(...) or updateAcl(...) (or the corresponding mqadmin/ACL update command) with a PolicyEntry whose actions field is null or an empty list, e.g. a JSON ACL document that omits the \"actions\" array.","commonSituations":"Hand-written ACL policy JSON where the actions key was forgotten; a management UI or script that builds PolicyEntry objects programmatically and never sets actions; deserialization of a policy document from an older schema that used a different field name.","solutions":["Add an explicit actions array (e.g. [\"PUB\",\"SUB\"]) to the policy entry being created or updated","If building PolicyEntry in Java, call entry.setActions(Arrays.asList(Action.PUB, Action.SUB)) before submit","Validate the ACL document against the current PolicyEntry schema (check for typos like \"action\" instead of \"actions\" that would silently deserialize to null)"],"exampleFix":"// before\nPolicyEntry entry = new PolicyEntry();\nentry.setResource(Resource.of(ResourceType.TOPIC, \"T\"));\nentry.setDecision(Decision.ALLOW);\nmetadataManager.createAcl(new Acl(Subject.of(\"User\", \"alice\"), Collections.singletonList(entry)));\n\n// after\nPolicyEntry entry = new PolicyEntry();\nentry.setResource(Resource.of(ResourceType.TOPIC, \"T\"));\nentry.setActions(Arrays.asList(Action.PUB, Action.SUB));\nentry.setDecision(Decision.ALLOW);\nmetadataManager.createAcl(new Acl(Subject.of(\"User\", \"alice\"), Collections.singletonList(entry)));","handlingStrategy":"validation","validationCode":"boolean hasActions(PolicyEntry entry) {\n    return entry != null && entry.getActions() != null && !entry.getActions().isEmpty();\n}\n// before metadataManager.createAcl(acl):\nfor (PolicyEntry e : acl.getPolicies()) {\n    if (!hasActions(e)) throw new IllegalArgumentException(\"policy missing actions\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    metadataManager.createAcl(acl).join();\n} catch (CompletionException | AuthorizationException e) {\n    // validate message, fix the ACL document, resubmit\n}","preventionTips":["Lint ACL JSON documents for required fields (resources, actions, decision) before submission","Build PolicyEntry via a factory method that enforces non-empty actions","Run acl validation in CI for any ACL files kept in version control"],"tags":["auth","authorization","acl","validation","rocketmq"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}