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
- Flatten the config so orderer orgs contain only Values and Policies, no Groups
- Move any nested groups to the correct level (Channel > Groups > Orderer > Groups > <OrgName>)
- 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
- Keep orderer org groups as leaves: only Values and Policies inside
- Generate profiles with configtxgen instead of hand-assembling ConfigGroups
- Validate group nesting with configtxlator proto_decode before submission
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
- [channel %s] cannot create channel because ChannelConfig is
- no orderer section in channel config for channel [%s].
- no policies in config block
- no orderer section in config block
- no orderer config in bundle
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/4dd9acf82125725a.
Report an issue: GitHub.