{"record":{"id":"aa6e623cd1d082ea","repo":"apache/rocketmq","slug":"subscription-group-config-is-null","errorCode":null,"errorMessage":"subscription group config is null.","messagePattern":"subscription group config is null\\.","errorType":"exception","errorClass":"AuthorizationException","httpStatus":null,"severity":"error","filePath":"auth/src/main/java/org/apache/rocketmq/auth/authorization/builder/DefaultAuthorizationContextBuilder.java","lineNumber":516,"sourceCode":"                    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\");\n                    TopicQueueMappingDetail mappingDetail = decodeRequiredBody(\n                        command, TopicQueueMappingDetail.class, \"topic queue mapping\");\n                    if (!StringUtils.equals(\n                        staticTopic, requireResource(mappingDetail.getTopic(), \"mapping topic\"))) {\n                        throw new AuthorizationException(\"mapping topic does not match topic header.\");","sourceCodeStart":498,"sourceCodeEnd":534,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/auth/src/main/java/org/apache/rocketmq/auth/authorization/builder/DefaultAuthorizationContextBuilder.java#L498-L534","documentation":"Thrown while iterating groupConfigList of an UPDATE_AND_CREATE_SUBSCRIPTIONGROUP_LIST request when an individual SubscriptionGroupConfig element is null. The builder immediately dereferences groupConfig.getGroupName(), so any null slot aborts context building with AuthorizationException before the CREATE permissions are evaluated.","triggerScenarios":"A body like {\"groupConfigList\":[null,...]} — null elements from a mapping step, placeholder-filled lists, or JSON produced by a non-Jackson encoder that emits nulls for absent entries.","commonSituations":"Pipelines converting YAML/CSV group definitions to SubscriptionGroupConfig where failed conversions become null; hand-built JSON arrays with literal null tokens.","solutions":["Filter null elements from the list before building the request body.","Make the conversion step fail loudly on invalid entries instead of emitting null.","Add a unit assertion that every element of the outgoing list is non-null."],"exampleFix":"// before\nList<SubscriptionGroupConfig> list = parseAll(input);\nbody.setGroupConfigList(list);\n\n// after\nList<SubscriptionGroupConfig> list = parseAll(input).stream()\n    .filter(Objects::nonNull).collect(toList());\nif (list.isEmpty()) { return; }\nbody.setGroupConfigList(list);","handlingStrategy":"validation","validationCode":"List<SubscriptionGroupConfig> clean = groupConfigList == null ? List.of()\n    : groupConfigList.stream().filter(Objects::nonNull).collect(toList());\nif (clean.isEmpty()) { return; }","typeGuard":null,"tryCatchPattern":"try { admin.updateSubscriptionGroupList(body); }\ncatch (AuthorizationException e) {\n    if (\"subscription group config is null.\".equals(e.getMessage())) { filterNullsAndRetry(); return; }\n    throw e;\n}","preventionTips":["Never allow null placeholders in request lists","Validate list elements, not just the list itself"],"tags":["rocketmq","authorization","admin-api","consumer-group","null-safety"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}