{"record":{"id":"314718c4e0e44bcb","repo":"hyperledger/fabric","slug":"organizations-do-not-support-sub-groups","errorCode":null,"errorMessage":"organizations do not support sub-groups","messagePattern":"organizations do not support sub-groups","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/channelconfig/organization.go","lineNumber":41,"sourceCode":"// OrganizationProtos are used to deserialize the organization config\ntype OrganizationProtos struct {\n\tMSP *mspprotos.MSPConfig\n}\n\n// OrganizationConfig stores the configuration for an organization\ntype OrganizationConfig struct {\n\tprotos *OrganizationProtos\n\n\tmspConfigHandler *MSPConfigHandler\n\tmsp              msp.MSP\n\tmspID            string\n\tname             string\n}\n\n// NewOrganizationConfig creates a new config for an organization\nfunc NewOrganizationConfig(name string, orgGroup *cb.ConfigGroup, mspConfigHandler *MSPConfigHandler) (*OrganizationConfig, error) {\n\tif len(orgGroup.Groups) > 0 {\n\t\treturn nil, fmt.Errorf(\"organizations do not support sub-groups\")\n\t}\n\n\toc := &OrganizationConfig{\n\t\tprotos:           &OrganizationProtos{},\n\t\tname:             name,\n\t\tmspConfigHandler: mspConfigHandler,\n\t}\n\n\tif err := DeserializeProtoValuesFromGroup(orgGroup, oc.protos); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to deserialize values\")\n\t}\n\n\tif err := oc.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn oc, nil\n}","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/channelconfig/organization.go#L23-L59","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\norgGroup := &cb.ConfigGroup{\n  Values: map[string]*cb.ConfigValue{...},\n  Groups: map[string]*cb.ConfigGroup{\"Peer1\": {...}},\n}\n// after\norgGroup := &cb.ConfigGroup{\n  Values: map[string]*cb.ConfigValue{...},\n}","handlingStrategy":"type-guard","validationCode":"func orgGroupIsValid(g *cb.ConfigGroup) bool {\n\treturn g != nil && len(g.Groups) == 0 && len(g.Values) > 0\n}","typeGuard":"func isFlatOrgGroup(g *cb.ConfigGroup) bool {\n\treturn len(g.Groups) == 0\n}","tryCatchPattern":"oc, err := channelconfig.NewOrganizationConfig(name, orgGroup, mspHandler)\nif err != nil && err.Error() == \"organizations do not support sub-groups\" {\n\treturn fmt.Errorf(\"flatten the org group: nested groups must live under Orderer/Application groups: %w\", err)\n}","preventionTips":["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"],"tags":["hyperledger-fabric","channelconfig","structure","validation"],"backgroundTag":"invalid-config-group-structure","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}