hyperledger/fabric · error

ConfigGroup not found at group path: %s

Error message

ConfigGroup not found at group path: %s

What it means

recurseConfigMap found an entry at 'groups/<path>' in the configMap, but the entry does not wrap an actual cb.ConfigGroup (comparable.ConfigGroup is nil). The comparable type is a union of ConfigGroup/ConfigValue/ConfigPolicy, so this means the wrong kind of element was stored under a group path.

Source

Thrown at common/configtx/configmap.go:120

// configMapToConfig is intended to be called from outside this file
// It takes a configMap and converts it back into a *cb.ConfigGroup structure
func configMapToConfig(configMap map[string]comparable, rootGroupKey string) (*cb.ConfigGroup, error) {
	rootPath := pathSeparator + rootGroupKey
	return recurseConfigMap(rootPath, configMap)
}

// recurseConfigMap is used only internally by configMapToConfig
// Note, this function no longer mutates the cb.Config* entries within configMap
func recurseConfigMap(path string, configMap map[string]comparable) (*cb.ConfigGroup, error) {
	groupPath := groupPrefix + path
	group, ok := configMap[groupPath]
	if !ok {
		return nil, errors.Errorf("missing group at path: %s", groupPath)
	}

	if group.ConfigGroup == nil {
		return nil, errors.Errorf("ConfigGroup not found at group path: %s", groupPath)
	}

	newConfigGroup := protoutil.NewConfigGroup()
	proto.Merge(newConfigGroup, group.ConfigGroup)

	for key := range group.Groups {
		updatedGroup, err := recurseConfigMap(path+pathSeparator+key, configMap)
		if err != nil {
			return nil, err
		}
		newConfigGroup.Groups[key] = updatedGroup
	}

	for key := range group.Values {
		valuePath := valuePrefix + path + pathSeparator + key
		value, ok := configMap[valuePath]
		if !ok {
			return nil, errors.Errorf("missing value at path: %s", valuePath)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix the map construction so every 'groups/<path>' key holds comparable{ConfigGroup: ...}.
  2. Regenerate the map with configtx.NewComparableConfig to guarantee path/prefix consistency.
  3. Check constants groupPrefix/valuePrefix/policyPrefix usage if building keys manually — the prefix must match the payload kind.
  4. Log the comparable at the reported path and correct the wrong kind stored there.

Example fix

// before
configMap["groups/Application"] = comparable{ConfigValue: someValue}
// after
configMap["groups/Application"] = comparable{ConfigGroup: appGroup}
Defensive patterns

Strategy: validation

Validate before calling

func groupEntryIsGroup(configMap map[string]configtx.Comparable, path string) bool {
	c, ok := configMap["groups/"+path]
	return ok && c.ConfigGroup != nil
}

Type guard

func asConfigGroup(c comparable) (*cb.ConfigGroup, bool) {
	if c.ConfigGroup == nil {
		return nil, false
	}
	return c.ConfigGroup, true
}

Try / catch

// errors are returned, not panicked
config, err := configtx.ConfigMapToConfig(configMap)
if err != nil {
	return fmt.Errorf("non-group payload under group path: %w", err)
}

Prevention

When it happens

Trigger: recurseConfigMap encountering a configMap entry keyed as a group whose comparable has ConfigGroup == nil — e.g. a ConfigValue or ConfigPolicy stored under a 'groups/...' key, or a zero-value comparable inserted by buggy map construction.

Common situations: Hand-built maps with path/prefix confusion (groupPrefix vs valuePrefix); deserialization that left the ConfigGroup unset; tests seeding placeholder comparables without payloads.

Related errors


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