{"record":{"id":"a9b75319e2826242","repo":"hyperledger/fabric","slug":"config-update-contains-changes-to-groups-within-th","errorCode":null,"errorMessage":"config update contains changes to groups within the %s group","messagePattern":"config update contains changes to groups within the (.+?) group","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/msgprocessor/maintenancefilter.go","lineNumber":193,"sourceCode":"\tif err != nil {\n\t\treturn errors.Wrap(err, \"config update unmarshalling error\")\n\t}\n\n\tif len(configUpdate.WriteSet.Groups) == 0 {\n\t\treturn errors.New(\"config update contains no changes\")\n\t}\n\n\tif len(configUpdate.WriteSet.Values) > 0 {\n\t\treturn errors.Errorf(\"config update contains changes to values in group %s\", channelconfig.ChannelGroupKey)\n\t}\n\n\tif len(configUpdate.WriteSet.Groups) > 1 {\n\t\treturn errors.New(\"config update contains changes to more than one group\")\n\t}\n\n\tif ordGroup, ok1 := configUpdate.WriteSet.Groups[channelconfig.OrdererGroupKey]; ok1 {\n\t\tif len(ordGroup.Groups) > 0 {\n\t\t\treturn errors.Errorf(\"config update contains changes to groups within the %s group\",\n\t\t\t\tchannelconfig.OrdererGroupKey)\n\t\t}\n\n\t\tif _, ok2 := ordGroup.Values[channelconfig.ConsensusTypeKey]; !ok2 {\n\t\t\treturn errors.Errorf(\"config update does not contain the %s value\", channelconfig.ConsensusTypeKey)\n\t\t}\n\n\t\tif len(ordGroup.Values) > 1 {\n\t\t\treturn errors.Errorf(\"config update contain more then just the %s value in the %s group\",\n\t\t\t\tchannelconfig.ConsensusTypeKey, channelconfig.OrdererGroupKey)\n\t\t}\n\t} else {\n\t\treturn errors.Errorf(\"update does not contain the %s group\", channelconfig.OrdererGroupKey)\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/msgprocessor/maintenancefilter.go#L175-L211","documentation":"This error is thrown during consensus-type migration (maintenance mode) when a channel config update includes sub-groups nested inside the Orderer group. During migration, the config update written to the Orderer group must contain ONLY the ConsensusType value change — any nested group changes (e.g. changes to the Application or Consortiums groups inside Orderer) are rejected because they would alter more than the migration allows.","triggerScenarios":"Calling msgprocessor inspect during maintenance mode with a configUpdate whose WriteSet contains OrdererGroupKey in WriteSet.Groups, but where ordGroup.Groups is non-empty (sub-group entries inside the Orderer group).","commonSituations":"Admins preparing a Raft-to-BFT consensus-type migration who bundle other config edits (e.g. moving a consortium, adding orderer endpoints group changes) into the same update transaction; tooling that generates deltas from a full config rather than the single ConsensusType change.","solutions":["Remove all nested group entries under the Orderer group from the WriteSet so only the Orderer group itself with the ConsensusType value change remains.","Recompute the config delta against the latest channel config so only the consensus_type value differs.","Split unrelated configuration changes into separate, post-migration config updates."],"exampleFix":"// before\nWriteSet.Groups[\"Orderer\"].Groups[\"OrdererOrg\"] = modifiedOrgGroup // nested group change\n// after\nWriteSet.Groups[\"Orderer\"].Groups = nil\nWriteSet.Groups[\"Orderer\"].Values[\"ConsensusType\"] = newConsensusTypeValue","handlingStrategy":"validation","validationCode":"if len(update.GetWriteSet().Groups) == 1 {\n    if ord, ok := update.GetWriteSet().Groups[\"Orderer\"]; ok && len(ord.Groups) > 0 {\n        return errors.New(\"nested groups under Orderer not allowed during migration\")\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate the delta with configtxlator rather than hand-editing the full config.","During migration, touch only the Orderer group and only its ConsensusType value.","Diff the proposed update against the current config before submitting."],"tags":["hyperledger-fabric","config-update","consensus-migration"],"backgroundTag":"config-update-rejected","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"}