{"record":{"id":"2dbe30e119a20b31","repo":"hyperledger/fabric","slug":"key-config-channelgroup-groups-s-is-missing","errorCode":null,"errorMessage":"key Config.ChannelGroup.Groups[%s] is missing","messagePattern":"key Config\\.ChannelGroup\\.Groups\\[(.+?)\\] is missing","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/support/config/support.go","lineNumber":239,"sourceCode":"\t\t\toutput[fabricConfig.Name] = fabricConfig\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc ValidateConfig(c *common.Config) error {\n\tif c.ChannelGroup == nil {\n\t\treturn errors.New(\"field Config.ChannelGroup is nil\")\n\t}\n\tgrps := c.ChannelGroup.Groups\n\tif grps == nil {\n\t\treturn errors.New(\"field Config.ChannelGroup.Groups is nil\")\n\t}\n\tfor _, field := range []string{channelconfig.OrdererGroupKey, channelconfig.ApplicationGroupKey} {\n\t\tgrp, exists := grps[field]\n\t\tif !exists {\n\t\t\treturn fmt.Errorf(\"key Config.ChannelGroup.Groups[%s] is missing\", field)\n\t\t}\n\t\tif grp.Groups == nil {\n\t\t\treturn fmt.Errorf(\"key Config.ChannelGroup.Groups[%s].Groups is nil\", field)\n\t\t}\n\t}\n\tif c.ChannelGroup.Values == nil {\n\t\treturn errors.New(\"field Config.ChannelGroup.Values is nil\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":221,"sourceCodeEnd":250,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/support/config/support.go#L221-L250","documentation":"ValidateConfig checks that both required sub-groups exist under Config.ChannelGroup.Groups: channelconfig.OrdererGroupKey (\"Orderer\") and channelconfig.ApplicationGroupKey (\"Application\"). If either key is absent, the channel config is structurally invalid for discovery and this formatted error names the missing key; Config wraps it with 'config is invalid' and fails the discovery request.","triggerScenarios":"A channel config whose Groups map exists but lacks \"Orderer\" or \"Application\": (1) application-only or test configs that omit the Orderer group; (2) system-channel or non-standard configs missing the Application group; (3) configs built by tooling that only added one of the two groups; (4) mutated config maps that deleted a group during an update.","commonSituations":"Configuring discovery against a channel created without an Application section; test fixtures with only an Orderer group; automated config-edit scripts removing a group; fabric versions/networks where the channel was created from a minimal profile.","solutions":["Recreate the channel config from a configtx.yaml profile that defines both Orderer and Application organizations so both groups are present.","If the Application group was intentionally omitted (e.g. orderer-only channel), the discovery service cannot serve org/MSP data for it; use a standard application channel instead.","Check configtxlator output of the latest config block to confirm which group is missing, then perform a config update adding the missing group.","Extend fixtures/mocks in tests to include both grps[channelconfig.OrdererGroupKey] and grps[channelconfig.ApplicationGroupKey] with non-nil Groups maps."],"exampleFix":"// before: only Orderer group\nGroups: map[string]*common.ConfigGroup{\n  channelconfig.OrdererGroupKey: ordererGroup,\n}\n\n// after: both required groups\nGroups: map[string]*common.ConfigGroup{\n  channelconfig.OrdererGroupKey:     ordererGroup,\n  channelconfig.ApplicationGroupKey: applicationGroup,\n}","handlingStrategy":"validation","validationCode":"if err := config.ValidateConfig(cfg); err != nil {\n\treturn err\n}\n// Optional stricter pre-check naming each required group:\nfor _, key := range []string{channelconfig.OrdererGroupKey, channelconfig.ApplicationGroupKey} {\n\tgrp, ok := cfg.ChannelGroup.Groups[key]\n\tif !ok {\n\t\treturn fmt.Errorf(\"channel config lacks %s group\", key)\n\t}\n\tif grp.Groups == nil {\n\t\treturn fmt.Errorf(\"%s group has nil Groups map\", key)\n\t}\n}","typeGuard":"func hasRequiredGroups(c *common.Config) bool {\n\tif c == nil || c.ChannelGroup == nil || c.ChannelGroup.Groups == nil {\n\t\treturn false\n\t}\n\t_, o := c.ChannelGroup.Groups[channelconfig.OrdererGroupKey]\n\t_, a := c.ChannelGroup.Groups[channelconfig.ApplicationGroupKey]\n\treturn o && a\n}","tryCatchPattern":"res, err := support.Config(channel)\nif err != nil {\n\tif strings.Contains(err.Error(), \"is missing\") && strings.Contains(err.Error(), \"Groups[\") {\n\t\treturn nil, fmt.Errorf(\"channel %s is missing a required Orderer/Application group: %w\", channel, err)\n\t}\n\treturn nil, err\n}","preventionTips":["Create channels from configtx.yaml profiles that define both Orderer and Application organizations.","Review any scripted channel-config edits for group deletions before submitting update transactions.","Inspect the latest config block with configtxlator to confirm both groups exist before pointing discovery clients at the channel.","Include both required group keys in every test fixture used with discovery support."],"tags":["hyperledger-fabric","service-discovery","config-validation","missing-key"],"backgroundTag":"missing-config-field","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}