hyperledger/fabric · error

key Config.ChannelGroup.Groups[%s].Groups is nil

Error message

key Config.ChannelGroup.Groups[%s].Groups is nil

What it means

This error comes from Hyperledger Fabric's discovery service config validation (ValidateConfig in discovery/support/config/support.go). When building a channel config from a protobuf Config, the code iterates over the Orderer and Application group keys and requires each ConfigGroup to exist AND to have a non-nil sub-Groups map. A nil Groups map means the channel config was built without proper Orderer/Application sub-groups, so discovery cannot parse the channel hierarchy.

Source

Thrown at discovery/support/config/support.go:242

	return nil
}

func ValidateConfig(c *common.Config) error {
	if c.ChannelGroup == nil {
		return errors.New("field Config.ChannelGroup is nil")
	}
	grps := c.ChannelGroup.Groups
	if grps == nil {
		return errors.New("field Config.ChannelGroup.Groups is nil")
	}
	for _, field := range []string{channelconfig.OrdererGroupKey, channelconfig.ApplicationGroupKey} {
		grp, exists := grps[field]
		if !exists {
			return fmt.Errorf("key Config.ChannelGroup.Groups[%s] is missing", field)
		}
		if grp.Groups == nil {
			return fmt.Errorf("key Config.ChannelGroup.Groups[%s].Groups is nil", field)
		}
	}
	if c.ChannelGroup.Values == nil {
		return errors.New("field Config.ChannelGroup.Values is nil")
	}
	return nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the Config is produced by the standard channel config toolchain (configtxgen / channel config update flow) so Orderer and Application groups each contain a populated Groups map
  2. If constructing common.Config manually, initialize grp.Groups = map[string]*common.ConfigGroup{} (with required sub-groups) instead of leaving it nil
  3. Validate the serialized channel config block with configtxlator before feeding it to the discovery support

Example fix

// before
grp, _ := cfg.ChannelGroup.Groups[channelconfig.ApplicationGroupKey]
grp.Values = ...
// Groups left nil

// after
grp, _ := cfg.ChannelGroup.Groups[channelconfig.ApplicationGroupKey]
if grp.Groups == nil {
    grp.Groups = make(map[string]*common.ConfigGroup)
}
grp.Groups["MyOrg"] = &common.ConfigGroup{Groups: map[string]*common.ConfigGroup{}, ...}
Defensive patterns

Strategy: validation

Validate before calling

func hasGroups(cfg *common.Config) bool {
    if cfg == nil || cfg.ChannelGroup == nil || cfg.ChannelGroup.Groups == nil {
        return false
    }
    for _, k := range []string{"Orderer", "Application"} {
        g, ok := cfg.ChannelGroup.Groups[k]
        if !ok || g == nil || g.Groups == nil {
            return false
        }
    }
    return true
}
// if !hasGroups(cfg) { fix config before ValidateConfig }

Type guard

func grp, ok := cfg.ChannelGroup.Groups["Orderer"]; ok && grp != nil && grp.Groups != nil; grp

Prevention

When it happens

Trigger: Calling ValidateConfig (directly or via NewConfig support construction) with a *common.Config whose ChannelGroup.Groups["Orderer"] or ChannelGroup.Groups["Application"] exists but has Groups == nil — e.g. a config created programmatically that sets the group value but never initializes its nested Groups map, or a config decoded from truncated/malformed channel config bytes.

Common situations: Building channel config protobufs by hand for unit tests or tooling; passing a partial Config (e.g. only Consortiums or only the root group populated) into the discovery support; upgrading Fabric versions and feeding legacy config blobs that lack Orderer/Application sub-groups.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/573db5315da35521. Report an issue: GitHub.