hyperledger/fabric · error
organizations do not support sub-groups
Error message
organizations do not support sub-groups
What it means
Fabric organization config groups may contain only Values, not nested Groups. NewOrganizationConfig rejects any org group with sub-groups, since an organization maps to MSP config plus values, and nesting would be structurally meaningless.
Source
Thrown at common/channelconfig/organization.go:41
// OrganizationProtos are used to deserialize the organization config
type OrganizationProtos struct {
MSP *mspprotos.MSPConfig
}
// OrganizationConfig stores the configuration for an organization
type OrganizationConfig struct {
protos *OrganizationProtos
mspConfigHandler *MSPConfigHandler
msp msp.MSP
mspID string
name string
}
// NewOrganizationConfig creates a new config for an organization
func NewOrganizationConfig(name string, orgGroup *cb.ConfigGroup, mspConfigHandler *MSPConfigHandler) (*OrganizationConfig, error) {
if len(orgGroup.Groups) > 0 {
return nil, fmt.Errorf("organizations do not support sub-groups")
}
oc := &OrganizationConfig{
protos: &OrganizationProtos{},
name: name,
mspConfigHandler: mspConfigHandler,
}
if err := DeserializeProtoValuesFromGroup(orgGroup, oc.protos); err != nil {
return nil, errors.Wrap(err, "failed to deserialize values")
}
if err := oc.Validate(); err != nil {
return nil, err
}
return oc, nil
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Remove all nested groups under the organization group; keep only Values (MSP, etc.)
- Place any node/peer entries under Application or Orderer group Organizations paths instead, not as children of the org
- Rebuild the config update with configtxgen or supported tooling
Example fix
// before
orgGroup := &cb.ConfigGroup{
Values: map[string]*cb.ConfigValue{...},
Groups: map[string]*cb.ConfigGroup{"Peer1": {...}},
}
// after
orgGroup := &cb.ConfigGroup{
Values: map[string]*cb.ConfigValue{...},
} Defensive patterns
Strategy: type-guard
Validate before calling
func orgGroupIsValid(g *cb.ConfigGroup) bool {
return g != nil && len(g.Groups) == 0 && len(g.Values) > 0
} Type guard
func isFlatOrgGroup(g *cb.ConfigGroup) bool {
return len(g.Groups) == 0
} Try / catch
oc, err := channelconfig.NewOrganizationConfig(name, orgGroup, mspHandler)
if err != nil && err.Error() == "organizations do not support sub-groups" {
return fmt.Errorf("flatten the org group: nested groups must live under Orderer/Application groups: %w", err)
} Prevention
- Model orgs as Value-only groups in any custom config tooling
- Keep per-node entries under the Orderer/Application Organizations, not under the org itself
- Validate generated cb.ConfigGroup trees against the Fabric schema before submitting updates
When it happens
Trigger: Crafting or programmatically building a cb.ConfigGroup for an organization that includes a Groups map (e.g. hand-assembled config update JSON/proto, or configtx template that nests under an org).
Common situations: Hand-written config update envelopes from tooling that misplaces sub-groups under an Organization group; migrating legacy config and accidentally nesting per-node groups under an org; malformed configtx addons.
Related errors
- MSP for org %s has empty MSP ID
- '%s' not equal <newest|oldest|config|(number)>
- unmarshalling block: %s
- specified --channelID %s does not match channel ID %s in con
- unmarshalling envelope: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/314718c4e0e44bcb.
Report an issue: GitHub.