{"record":{"id":"d1d5cc2d8d80e060","repo":"hyperledger/fabric","slug":"new-channel-has-consenter-that-is-not-part-of-syst","errorCode":null,"errorMessage":"new channel has consenter that is not part of system consenter set","messagePattern":"new channel has consenter that is not part of system consenter set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/etcdraft/chain.go","lineNumber":1519,"sourceCode":"\tif err := proto.Unmarshal(newOrdererConfig.ConsensusMetadata(), newMetadata); err != nil {\n\t\treturn errors.Wrap(err, \"failed to unmarshal new etcdraft metadata configuration\")\n\t}\n\n\tverifyOpts, err := createX509VerifyOptions(newOrdererConfig)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to create x509 verify options from old and new orderer config\")\n\t}\n\n\tif err := VerifyConfigMetadata(newMetadata, verifyOpts); err != nil {\n\t\treturn errors.Wrap(err, \"invalid new config metadata\")\n\t}\n\n\tif newChannel {\n\t\t// check if the consenters are a subset of the existing consenters (system channel consenters)\n\t\tset := ConsentersToMap(oldMetadata.GetConsenters())\n\t\tfor _, c := range newMetadata.GetConsenters() {\n\t\t\tif !set.Exists(c) {\n\t\t\t\treturn errors.New(\"new channel has consenter that is not part of system consenter set\")\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// create the dummy parameters for ComputeMembershipChanges\n\tc.raftMetadataLock.RLock()\n\tdummyOldBlockMetadata := proto.Clone(c.opts.BlockMetadata).(*etcdraft.BlockMetadata)\n\tc.raftMetadataLock.RUnlock()\n\n\tdummyOldConsentersMap := CreateConsentersMap(dummyOldBlockMetadata, oldMetadata)\n\tchanges, err := ComputeMembershipChanges(dummyOldBlockMetadata, dummyOldConsentersMap, newMetadata.GetConsenters())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// new config metadata was verified above. Additionally need to check new consenters for certificates expiration\n\tfor _, c := range changes.AddedNodes {","sourceCodeStart":1501,"sourceCodeEnd":1537,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/etcdraft/chain.go#L1501-L1537","documentation":"During creation of a new application channel (newChannel=true), the etcdraft consenter set must be a subset of the system channel's consenters (orderer/consensus/etcdraft/chain.go:1519). This error means the new channel's raft metadata contains a consenter (host/port) that is not present in the old (system channel) metadata set. It is a hard check in VerifyConfigMetadata, not a transient failure.","triggerScenarios":"A channel creation request whose etcdraft ConfigMetadata lists a consenter with a host:port combination absent from the system channel's consenters.","commonSituations":"Hand-editing the channel creation profile to add an extra orderer before it was added to the system channel; typos in host or port differing from the system channel entry; Fabric migration flows where the new profile was generated from a stale system channel config.","solutions":["Add the missing consenter to the system channel first, wait for its block/certificates to be committed, then create the channel","Remove the extraneous consenter from the new channel's configtx profile","Compare host:port strings exactly (including port) with the system channel consenters"],"exampleFix":"// before (new channel profile)\nConsenters: [{Host: orderer3.example.com, Port: 7050}] // not in system channel\n// after\nConsenters: [{Host: orderer1.example.com, Port: 7050}, {Host: orderer2.example.com, Port: 7050}] // subset of system channel consenters","handlingStrategy":"validation","validationCode":"sysSet := ConsentersToMap(systemChannelMetadata.GetConsenters())\nfor _, c := range newChannelMetadata.GetConsenters() {\n    if !sysSet.Exists(c) {\n        return fmt.Errorf(\"consenter %s:%d must first be added to the system channel\", c.GetHost(), c.GetPort())\n    }\n}","typeGuard":"func subsetOfSystem(new, sys []*common.Consenter) bool {\n    set := ConsentersToMap(sys)\n    for _, c := range new {\n        if !set.Exists(c) { return false }\n    }\n    return true\n}","tryCatchPattern":null,"preventionTips":["Add new orderers to the system channel before using them in app channel profiles","Keep host:port values identical across profiles","Generate profiles from the current system channel config, not stale copies"],"tags":["raft","consenters","channel-creation"],"backgroundTag":"consenter-not-in-system-channel-set","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"}