hyperledger/fabric · error

OrdererOrg config does not allow sub-groups

Error message

OrdererOrg config does not allow sub-groups

What it means

NewOrdererOrgConfig builds an orderer org config from a ConfigGroup. Orderer orgs must be leaf groups — they may not contain nested sub-groups. If orgGroup.Groups is non-empty, the construction fails with 'OrdererOrg config does not allow sub-groups'.

Source

Thrown at common/channelconfig/orderer.go:89

type OrdererOrgConfig struct {
	*OrganizationConfig
	protos *OrdererOrgProtos
	name   string
}

// Endpoints returns the set of addresses this ordering org exposes as orderers
func (oc *OrdererOrgConfig) Endpoints() []string {
	if oc.protos == nil || oc.protos.Endpoints == nil {
		return nil
	}

	return oc.protos.Endpoints.Addresses
}

// NewOrdererOrgConfig returns an orderer org config built from the given ConfigGroup.
func NewOrdererOrgConfig(orgName string, orgGroup *cb.ConfigGroup, mspConfigHandler *MSPConfigHandler, channelCapabilities ChannelCapabilities) (*OrdererOrgConfig, error) {
	if len(orgGroup.Groups) > 0 {
		return nil, fmt.Errorf("OrdererOrg config does not allow sub-groups")
	}

	if !channelCapabilities.OrgSpecificOrdererEndpoints() {
		if _, ok := orgGroup.Values[EndpointsKey]; ok {
			return nil, errors.Errorf("Orderer Org %s cannot contain endpoints value until V1_4_2+ capabilities have been enabled", orgName)
		}
	}

	protos := &OrdererOrgProtos{}
	orgProtos := &OrganizationProtos{}

	if err := DeserializeProtoValuesFromGroup(orgGroup, protos, orgProtos); err != nil {
		return nil, errors.Wrap(err, "failed to deserialize values")
	}

	ooc := &OrdererOrgConfig{
		name:   orgName,
		protos: protos,

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Flatten the config so orderer orgs contain only Values and Policies, no Groups
  2. Move any nested groups to the correct level (Channel > Groups > Orderer > Groups > <OrgName>)
  3. Re-run configtxgen with a corrected configtx.yaml profile to regenerate the config
Defensive patterns

Strategy: validation

Validate before calling

if len(orgGroup.Groups) > 0 {
    return fmt.Errorf("orderer org group must not contain sub-groups; found %d", len(orgGroup.Groups))
}

Type guard

func isLeafGroup(g *cb.ConfigGroup) bool { return len(g.Groups) == 0 }

Try / catch

cfg, err := NewOrdererOrgConfig(orgName, orgGroup, mspHandler, caps)
if err != nil && strings.Contains(err.Error(), "does not allow sub-groups") {
    log.Errorf("restructure config: nested groups under orderer org %s are invalid", orgName)
    return err
}

Prevention

When it happens

Trigger: Calling NewOrdererOrgConfig (via NewOrdererConfig during channel config construction) with an orderer org ConfigGroup that has nested Groups entries, e.g. misplaced orgs nested inside an orderer org group.

Common situations: configtx.yaml structured incorrectly so orgs or sub-groups end up under the Orderer group's org entries; programmatic config assembly that nests groups under an orderer org; copy-paste errors when editing config transactions.

Related errors


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