{"record":{"id":"b9af12b37c0994e8","repo":"hyperledger/fabric","slug":"not-a-smartbft-config-block","errorCode":null,"errorMessage":"not a SmartBFT config block","messagePattern":"not a SmartBFT config block","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/util.go","lineNumber":413,"sourceCode":"// It returns nil if true, else returns an error.\nfunc (conCert ConsenterCertificate) IsConsenterOfChannel(configBlock *cb.Block) error {\n\tif configBlock == nil {\n\t\treturn errors.New(\"nil block\")\n\t}\n\tenvelopeConfig, err := protoutil.ExtractEnvelope(configBlock, 0)\n\tif err != nil {\n\t\treturn err\n\t}\n\tbundle, err := channelconfig.NewBundleFromEnvelope(envelopeConfig, conCert.CryptoProvider)\n\tif err != nil {\n\t\treturn err\n\t}\n\toc, exists := bundle.OrdererConfig()\n\tif !exists {\n\t\treturn errors.New(\"no orderer config in bundle\")\n\t}\n\tif oc.ConsensusType() != \"BFT\" {\n\t\treturn errors.New(\"not a SmartBFT config block\")\n\t}\n\n\tfor _, consenter := range oc.Consenters() {\n\t\tif bytes.Equal(conCert.ConsenterCertificate, consenter.ServerTlsCert) || bytes.Equal(conCert.ConsenterCertificate, consenter.ClientTlsCert) {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn cluster.ErrNotInChannel\n}\n\ntype worker struct {\n\twork      [][]byte\n\tf         func([]byte)\n\tworkerNum int\n\tid        int\n}\n\nfunc (w *worker) doWork() {","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/util.go#L395-L431","documentation":"IsConsenterOfChannel only validates consenters for channels configured with consensus type BFT (Smart BFT). If the bundle's orderer config reports a different ConsensusType (e.g. etcdraft, solo), the block cannot be interpreted as a SmartBFT config and this error is returned.","triggerScenarios":"Calling IsConsenterOfChannel on a channel whose orderer group has ConsensusType other than \"BFT\" — e.g. an etcdraft channel — while the caller expects SmartBFT.","commonSituations":"Mixed-consensus network where a SmartBFT node receives an etcdraft channel's config block; migrating channels between consensus types but pointing at stale blocks; misconfigured configtx.yaml consensus.type.","solutions":["Ensure the channel's consensus.type is set to BFT in configtx.yaml and regenerate/commit the config block","Point IsConsenterOfChannel at a config block belonging to a BFT channel","If the channel should stay etcdraft, use the etcdraft cluster check instead of the SmartBFT one"],"exampleFix":"// configtx.yaml\nOrderer:\n  OrdererType: etcdraft\n// after\nOrderer:\n  OrdererType: BFT\n","handlingStrategy":"validation","validationCode":"bundle, _ := channelconfig.NewBundleFromEnvelope(env, cryptoProvider)\noc, ok := bundle.OrdererConfig()\nif ok && oc.ConsensusType() != \"BFT\" {\n    return errors.Errorf(\"channel consensus is %s, not BFT\", oc.ConsensusType())\n}","typeGuard":"func isBFTChannel(oc channelconfig.Orderer) bool {\n    return oc.ConsensusType() == \"BFT\"\n}","tryCatchPattern":"if err := IsConsenterOfChannel(env, cert); err != nil {\n    if strings.Contains(err.Error(), \"not a SmartBFT config block\") {\n        // route to the appropriate consensus-type checker\n    }\n}","preventionTips":["Set OrdererType: BFT in configtx.yaml for SmartBFT channels","Keep track of which channels use etcdraft vs BFT","Re-fetch the latest config block after consensus-type migration"],"tags":["hyperledger-fabric","orderer","smartbft","consensus-type"],"backgroundTag":"consensus-type-mismatch","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"}