{"record":{"id":"6033a8db27e06f05","repo":"apache/rocketmq","slug":"subscription-group-list-is-empty","errorCode":null,"errorMessage":"subscription group list is empty.","messagePattern":"subscription group list is empty\\.","errorType":"exception","errorClass":"AuthorizationException","httpStatus":null,"severity":"error","filePath":"auth/src/main/java/org/apache/rocketmq/auth/authorization/builder/DefaultAuthorizationContextBuilder.java","lineNumber":511,"sourceCode":"                    group = Resource.ofGroup(requireResource(\n                        decodeRequiredText(command, \"consumer group\"), \"consumer group\"));\n                    result.add(DefaultAuthorizationContext.of(subject, group, Action.UPDATE, sourceIp));\n                    break;\n                case RequestCode.UPDATE_AND_CREATE_SUBSCRIPTIONGROUP:\n                    SubscriptionGroupConfig subscriptionGroupConfig =\n                        RemotingSerializable.decode(command.getBody(), SubscriptionGroupConfig.class);\n                    if (subscriptionGroupConfig == null\n                        || StringUtils.isBlank(subscriptionGroupConfig.getGroupName())) {\n                        throw new AuthorizationException(\"subscription group is null.\");\n                    }\n                    result.add(DefaultAuthorizationContext.of(subject,\n                        Resource.ofGroup(subscriptionGroupConfig.getGroupName()), Action.CREATE, sourceIp));\n                    break;\n                case RequestCode.UPDATE_AND_CREATE_SUBSCRIPTIONGROUP_LIST:\n                    SubscriptionGroupList subscriptionGroupList = decodeRequiredBody(\n                        command, SubscriptionGroupList.class, \"subscription group list\");\n                    if (CollectionUtils.isEmpty(subscriptionGroupList.getGroupConfigList())) {\n                        throw new AuthorizationException(\"subscription group list is empty.\");\n                    }\n                    Set<String> subscriptionGroupResources = new LinkedHashSet<>();\n                    for (SubscriptionGroupConfig groupConfig : subscriptionGroupList.getGroupConfigList()) {\n                        if (groupConfig == null) {\n                            throw new AuthorizationException(\"subscription group config is null.\");\n                        }\n                        addUniqueContext(result, subscriptionGroupResources, subject,\n                            Resource.ofGroup(requireResource(groupConfig.getGroupName(), \"consumer group\")),\n                            Action.CREATE, sourceIp);\n                    }\n                    break;\n                case RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC:\n                    CreateTopicRequestHeader createTopicRequestHeader =\n                        command.decodeCommandCustomHeader(CreateTopicRequestHeader.class);\n                    if (createTopicRequestHeader == null) {\n                        throw new AuthorizationException(\"topic header is null.\");\n                    }\n                    String staticTopic = requireResource(createTopicRequestHeader.getTopic(), \"topic\");","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/auth/src/main/java/org/apache/rocketmq/auth/authorization/builder/DefaultAuthorizationContextBuilder.java#L493-L529","documentation":"Thrown for UPDATE_AND_CREATE_SUBSCRIPTIONGROUP_LIST when the decoded SubscriptionGroupList body has a null or empty groupConfigList. Analogous to the topic-list check: each SubscriptionGroupConfig would yield a group Resource for a CREATE authorization, so an empty list is rejected with AuthorizationException rather than creating zero contexts.","triggerScenarios":"Sending RequestCode.UPDATE_AND_CREATE_SUBSCRIPTIONGROUP_LIST with a body missing the 'groupConfigList' key, or with an empty array. Typically hit through bulk subscription-group creation APIs or tooling that batches SubscriptionGroupConfig objects.","commonSituations":"Bulk group provisioning from an empty config file or a filtered list that ended up empty; wrong JSON field name in a hand-rolled client so the list stays null after decode.","solutions":["Skip the RPC when the group config list is empty — it is a no-op anyway.","Ensure the serialized body contains a non-empty 'groupConfigList' array with the exact field name the broker expects.","Assert list size matches the number of source entries before serializing."],"exampleFix":"// before\nbody.setGroupConfigList(groups); // groups may be empty\nadmin.updateSubscriptionGroupList(body);\n\n// after\nif (groups == null || groups.isEmpty()) { return; }\nbody.setGroupConfigList(groups);\nadmin.updateSubscriptionGroupList(body);","handlingStrategy":"validation","validationCode":"if (CollectionUtils.isEmpty(groupConfigList)) { return; }\nbody.setGroupConfigList(groupConfigList);","typeGuard":null,"tryCatchPattern":"try { admin.updateSubscriptionGroupList(body); }\ncatch (AuthorizationException e) {\n    if (e.getMessage().contains(\"subscription group list is empty\")) { return; }\n    throw e;\n}","preventionTips":["Short-circuit empty batch operations client-side","Assert outgoing list sizes match source counts"],"tags":["rocketmq","authorization","admin-api","consumer-group","validation"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}