{"record":{"id":"45d2f9d1b589633e","repo":"hyperledger/fabric","slug":"supplied-system-channel-group-has-no-sub-groups","errorCode":null,"errorMessage":"supplied system channel group has no sub-groups","messagePattern":"supplied system channel group has no sub-groups","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configtxgen/encoder/encoder.go","lineNumber":506,"sourceCode":"\tchannelGroup, err := NewChannelGroup(conf)\n\tif err != nil {\n\t\treturn nil, errors.WithMessage(err, \"error parsing configuration\")\n\t}\n\n\tif _, ok := channelGroup.Groups[channelconfig.ApplicationGroupKey]; !ok {\n\t\treturn nil, errors.New(\"channel template configs must contain an application section\")\n\t}\n\n\tchannelGroup.Groups[channelconfig.ApplicationGroupKey].Values = nil\n\tchannelGroup.Groups[channelconfig.ApplicationGroupKey].Policies = nil\n\n\treturn channelGroup, nil\n}\n\nfunc ConfigTemplateFromGroup(conf *genesisconfig.Profile, cg *cb.ConfigGroup) (*cb.ConfigGroup, error) {\n\ttemplate := proto.Clone(cg).(*cb.ConfigGroup)\n\tif template.Groups == nil {\n\t\treturn nil, errors.Errorf(\"supplied system channel group has no sub-groups\")\n\t}\n\n\ttemplate.Groups[channelconfig.ApplicationGroupKey] = &cb.ConfigGroup{\n\t\tGroups: map[string]*cb.ConfigGroup{},\n\t\tPolicies: map[string]*cb.ConfigPolicy{\n\t\t\tchannelconfig.AdminsPolicyKey: {},\n\t\t},\n\t}\n\n\tconsortiums, ok := template.Groups[channelconfig.ConsortiumsGroupKey]\n\tif !ok {\n\t\treturn nil, errors.Errorf(\"supplied system channel group does not appear to be system channel (missing consortiums group)\")\n\t}\n\n\tif consortiums.Groups == nil {\n\t\treturn nil, errors.Errorf(\"system channel consortiums group appears to have no consortiums defined\")\n\t}\n","sourceCodeStart":488,"sourceCodeEnd":524,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/configtxgen/encoder/encoder.go#L488-L524","documentation":"ConfigTemplateFromGroup clones an existing system-channel config group and adapts it into a template for a new channel. If the cloned group has no Groups map at all, it cannot be a system channel group, so the library rejects it with this error. It protects against passing an empty or non-system-channel group.","triggerScenarios":"Calling ConfigTemplateFromGroup / MakeChannelCreationTransactionWithSystemChannelContext with a cb.ConfigGroup whose Groups map is nil — e.g. a nil or freshly constructed config group, or the group of a channel that has no sub-groups.","commonSituations":"Passing the config group of an application channel (or an empty group) instead of the ordering system channel's group when creating channels programmatically.","solutions":["Pass the ChannelGroup from the ordering system channel's current config (e.g. via the orderer's channel config retrieval).","Check that the group actually has Orderer/Consortiums/Application sub-groups before calling.","If constructing programmatically, build the group with NewChannelGroup for the system channel profile first."],"exampleFix":"// before\nvar cg *cb.ConfigGroup\ntemplate, err := encoder.ConfigTemplateFromGroup(profile, cg)\n// after\ncg, err := fetchSystemChannelGroup(ordererClient) // must contain sub-groups\ntemplate, err := encoder.ConfigTemplateFromGroup(profile, cg)","handlingStrategy":"type-guard","validationCode":"if cg == nil || cg.Groups == nil || len(cg.Groups) == 0 {\n    return errors.New(\"supplied group must be a populated system channel group\")\n}","typeGuard":"func isSystemChannelLikeGroup(cg *cb.ConfigGroup) bool {\n    return cg != nil && cg.Groups != nil && len(cg.Groups) > 0\n}","tryCatchPattern":"tmpl, err := encoder.ConfigTemplateFromGroup(profile, cg)\nif err != nil && strings.Contains(err.Error(), \"no sub-groups\") {\n    return errors.New(\"fetch the system channel config, not an empty group\")\n}","preventionTips":["Retrieve the system channel group from the orderer rather than constructing one.","Check group.GetGroups() is populated before adapting it into a template.","Use distinct names for system channel vs application channel configs to avoid mixups."],"tags":["hyperledger-fabric","configtx","system-channel","template"],"backgroundTag":"invalid-system-channel-group","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}