{"record":{"id":"d718cb0f30c88ff3","repo":"hyperledger/fabric","slug":"no-orderer-section-in-channel-config-for-channel","errorCode":null,"errorMessage":"no orderer section in channel config for channel [%s].","messagePattern":"no orderer section in channel config for channel \\[(.+?)\\]\\.","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/peer/gossip/mcs.go","lineNumber":186,"sourceCode":"\tcpm := s.channelPolicyManagerGetter.Manager(channelID)\n\tif cpm == nil {\n\t\treturn fmt.Errorf(\"Could not acquire policy manager for channel %s\", channelID)\n\t}\n\tmcsLogger.Debugf(\"Got policy manager for channel [%s]\", channelID)\n\n\t// Get block validation policy\n\tpolicy, ok := cpm.GetPolicy(policies.BlockValidation)\n\t// ok is true if it was the policy requested, or false if it is the default policy\n\tmcsLogger.Debugf(\"Got block validation policy for channel [%s] with flag [%t]\", channelID, ok)\n\n\tchConfig := s.channelConfigGetter(channelID)\n\tbftEnabled := chConfig.ChannelConfig().Capabilities().ConsensusTypeBFT()\n\n\tvar consenters []*pcommon.Consenter\n\tif bftEnabled {\n\t\tcfg, ok := chConfig.OrdererConfig()\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"no orderer section in channel config for channel [%s].\", channelID)\n\t\t}\n\t\tconsenters = cfg.Consenters()\n\t}\n\n\tverifier := protoutil.BlockSignatureVerifier(bftEnabled, consenters, policy)\n\treturn verifier(block.Header, block.Metadata)\n}\n\n// VerifyBlockAttestation returns nil when the header matches the metadata signature. It assumed the block.Data is nil\n// and therefore does not verify that Header.DataHash is equal to the hash of block.Data. This is used when the orderer\n// delivers a block with header & metadata only, as an attestation of block existence.\nfunc (s *MSPMessageCryptoService) VerifyBlockAttestation(chainID string, block *pcommon.Block) error {\n\tif block == nil {\n\t\treturn fmt.Errorf(\"Invalid Block on channel [%s]. Block is nil.\", chainID)\n\t}\n\tif block.Header == nil {\n\t\treturn fmt.Errorf(\"Invalid Block on channel [%s]. Header must be different from nil.\", chainID)\n\t}","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/peer/gossip/mcs.go#L168-L204","documentation":"While building the block signature verifier, the channel config had BFT consensus capability enabled (ConsensusTypeBFT is true) but chConfig.OrdererConfig() returned no Orderer section. Without the orderer config the service cannot obtain the consenters list needed to verify BFT block signatures, so it errors out.","triggerScenarios":"VerifyBlock or VerifyBlockAttestation runs on a channel whose config group enables the BFT consensus capability but lacks an orderer.config group — a malformed or incomplete channel configuration.","commonSituations":"Hand-edited or partially generated channel config where capabilities say BFT but the orderer group was dropped; config update that removed the Orderer section; mixing config blobs across channels when scripting channel creation; wrong config tree deserialization in tests.","solutions":["Inspect the channel config (configtxlator proto_decode) and confirm the Orderer group exists alongside the BFT capability.","Regenerate the channel config from a correct configtx.yaml that defines the Orderer section.","If the channel is not meant to be BFT, disable/align the ConsensusTypeBFT capability so consenters are not required.","Apply a config update re-adding the orderer config group, then retry block verification.","Verify peer is loading the latest committed channel config, not a stale one."],"exampleFix":"// before (configtx.yaml missing orderer group while BFT capability on)\nCapabilities:\n  Channel: &ChannelCapabilities{ConsensusType: BFT}\n// after: define the Orderer section\nOrderer: &OrdererDefaults\n  OrdererType: etcdraft\n  Capabilities: <<: *OrdererCapabilities  # BFT enabled together with orderer config present","handlingStrategy":"validation","validationCode":"cfg, ok := channelConfig.OrdererConfig()\nbft := channelConfig.ChannelConfig().Capabilities().ConsensusTypeBFT()\nif bft && !ok {\n    return fmt.Errorf(\"channel config invalid: BFT enabled but Orderer section missing\")\n}","typeGuard":"func hasOrdererConfigForBFT(envConfig *common.Config) bool {\n    oc, ok := channelconfig.OrdererConfig(envConfig)\n    return !envConfig.ChannelConfig().Capabilities().ConsensusTypeBFT() || ok && oc != nil\n}","tryCatchPattern":"if err := cryptoService.VerifyBlock(chainID, block); err != nil {\n    if strings.Contains(err.Error(), \"no orderer section\") {\n        log.Errorf(\"corrupt channel config for %s: reload config via config update\", chainID)\n    }\n    return err\n}","preventionTips":["Always define the Orderer section in configtx.yaml when BFT capability is enabled","Validate generated channel config with configtxlator before submitting","Never hand-edit channel config blobs; regenerate from configtx.yaml","Keep capabilities and orderer type settings consistent across the network"],"tags":["hyperledger-fabric","gossip","channel-config","bft","orderer"],"backgroundTag":"missing-orderer-channel-config","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"}