{"record":{"id":"6788eb32155d2421","repo":"hyperledger/fabric","slug":"empty-channel-group","errorCode":null,"errorMessage":"empty channel group","messagePattern":"empty channel group","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/configverifier.go","lineNumber":100,"sourceCode":"\tswitch chdr.Type {\n\tcase int32(common.HeaderType_CONFIG):\n\t\tconfigEnvelope := &common.ConfigEnvelope{}\n\t\tif err = proto.Unmarshal(payload.Data, configEnvelope); err != nil {\n\t\t\treturn fmt.Errorf(\"data unmarshalling error: %s\", err)\n\t\t}\n\t\treturn cbv.verifyConfigUpdateMsg(envelope, configEnvelope, chdr)\n\tdefault:\n\t\treturn errors.Errorf(\"unexpected envelope type %s\", common.HeaderType_name[chdr.Type])\n\t}\n}\n\nfunc (cbv *ConfigBlockValidator) checkConsentersMatchPolicy(conf *common.Config) error {\n\tif conf == nil {\n\t\treturn fmt.Errorf(\"empty Config\")\n\t}\n\n\tif conf.ChannelGroup == nil {\n\t\treturn fmt.Errorf(\"empty channel group\")\n\t}\n\n\tif len(conf.ChannelGroup.Groups) == 0 {\n\t\treturn fmt.Errorf(\"no groups in channel group\")\n\t}\n\n\tif conf.ChannelGroup.Groups[\"Orderer\"] == nil {\n\t\treturn fmt.Errorf(\"no 'Orderer' group in channel groups\")\n\t}\n\n\tif len(conf.ChannelGroup.Groups[\"Orderer\"].Values) == 0 {\n\t\treturn fmt.Errorf(\"no values in 'Orderer' group\")\n\t}\n\n\tif conf.ChannelGroup.Groups[\"Orderer\"].Values[\"Orderers\"] == nil {\n\t\treturn fmt.Errorf(\"no values in 'Orderer' group\")\n\t}\n","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/configverifier.go#L82-L118","documentation":"The channel-level Config must contain a ChannelGroup, which is the root of the channel's configuration hierarchy. A nil ChannelGroup means the config struct exists but is empty of channel configuration, so consenter/policy checks cannot proceed and 'empty channel group' is returned.","triggerScenarios":"checkConsentersMatchPolicy receiving a *common.Config whose ChannelGroup field is nil — e.g. a Config message that was allocated but never populated from a config block.","commonSituations":"Programmatically built Config structs with only metadata set; corrupt or truncated config blocks; test fixtures missing the ChannelGroup; protobuf unmarshalling of empty bytes into a Config.","solutions":["Populate Config.ChannelGroup with the full channel config tree (including Orderer/Application groups) before validation","Regenerate the config block with the configtxgen/configtxlator tooling rather than hand-assembling it","Re-fetch the config block from the ordering service if it appears corrupted"],"exampleFix":"// before\nconf := &common.Config{} // ChannelGroup nil\n// after\nconf := &common.Config{ChannelGroup: configtxChannelGroup}","handlingStrategy":"validation","validationCode":"func hasChannelGroup(conf *common.Config) bool {\n  return conf != nil && conf.ChannelGroup != nil\n}","typeGuard":"func hasChannelGroup(c *common.Config) bool { return c != nil && c.GetChannelGroup() != nil }","tryCatchPattern":"if err := cbv.ValidateConfig(envelope); err != nil {\n  if strings.Contains(err.Error(), \"empty channel group\") {\n    return fmt.Errorf(\"config missing channel group: %w\", err)\n  }\n  return err\n}","preventionTips":["Never hand-construct common.Config; derive it from a validated configtx","Run configtxlator proto_decode on generated config to confirm ChannelGroup exists","Add unit assertions that config fixtures contain ChannelGroup"],"tags":["hyperledger-fabric","smartbft","config-validation","channel-group"],"backgroundTag":"empty-configuration","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"}