{"record":{"id":"82191f573d8ae22b","repo":"hyperledger/fabric","slug":"invalid-bft-metadata-configuration","errorCode":null,"errorMessage":"invalid BFT metadata configuration","messagePattern":"invalid BFT metadata configuration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/msgprocessor/maintenancefilter.go","lineNumber":145,"sourceCode":"\t\tif nextOrdererConfig.ConsensusState() == orderer.ConsensusType_STATE_NORMAL {\n\t\t\treturn errors.Errorf(\"attempted to change consensus type from %s to %s, but next config ConsensusType.State is not in maintenance mode\",\n\t\t\t\tordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())\n\t\t}\n\n\t\tif !mf.permittedTargetConsensusTypes[nextOrdererConfig.ConsensusType()] {\n\t\t\treturn errors.Errorf(\"attempted to change consensus type from %s to %s, transition not supported\",\n\t\t\t\tordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())\n\t\t}\n\n\t\tif nextOrdererConfig.ConsensusType() == \"BFT\" {\n\t\t\tupdatedMetadata := &smartbft.Options{}\n\t\t\tif err := proto.Unmarshal(nextOrdererConfig.ConsensusMetadata(), updatedMetadata); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"failed to unmarshal BFT metadata configuration\")\n\t\t\t}\n\n\t\t\t_, err := util.ConfigFromMetadataOptions(1, updatedMetadata)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.New(\"invalid BFT metadata configuration\")\n\t\t\t}\n\n\t\t\terr = validateBFTConsenterMapping(ordererConfig, nextOrdererConfig)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"invalid BFT consenter mapping configuration\")\n\t\t\t}\n\t\t}\n\n\t\tlogger.Infof(\"[channel: %s] consensus-type migration: about to change from %s to %s\",\n\t\t\tmf.support.ChannelID(), ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())\n\t}\n\n\tif nextOrdererConfig.ConsensusState() != ordererConfig.ConsensusState() {\n\t\tlogger.Infof(\"[channel: %s] maintenance mode: ConsensusType.State about to change from %s to %s\",\n\t\t\tmf.support.ChannelID(), ordererConfig.ConsensusState(), nextOrdererConfig.ConsensusState())\n\t}\n\n\treturn nil","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/msgprocessor/maintenancefilter.go#L127-L163","documentation":"Returned when the BFT metadata unmarshals as smartbft.Options but util.ConfigFromMetadataOptions fails to derive a valid consensus configuration from it. The metadata is structurally a valid protobuf but semantically invalid (e.g. bad batch settings, invalid timeouts, or empty leader-related options).","triggerScenarios":"A maintenance-mode migration to BFT where the smartbft.Options in ConsensusMetadata contain values that ConfigFromMetadataOptions cannot convert into a valid localconfig consensus config (invalid numeric or duration fields, out-of-range options).","commonSituations":"Administrators crafting BFT metadata by hand with wrong units for timeouts, zero/negative batch sizes, or options copied from an incompatible Fabric version.","solutions":["Fix the smartbft.Options values so ConfigFromMetadataOptions can build a valid config (positive batch sizes, valid timeouts)","Start from a known-good BFT metadata generated by configtxgen/configtxlator for your Fabric version","Check orderer local config examples for the version you are migrating to and mirror the option values"],"exampleFix":"// before: invalid option\n\"RequestBatchMaxCount\": 0\n// after: valid option\n\"RequestBatchMaxCount\": 100","handlingStrategy":"validation","validationCode":"opts := &smartbft.Options{}\nif err := proto.Unmarshal(metadata, opts); err != nil { return err }\nif _, err := util.ConfigFromMetadataOptions(1, opts); err != nil {\n    return fmt.Errorf(\"BFT options semantically invalid: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start BFT metadata from a known-good template for your Fabric version","Use positive batch sizes and valid timeout units in smartbft.Options","Test the update on a disposable channel/network before applying to production"],"tags":["hyperledger-fabric","orderer","smartbft","config-validation"],"backgroundTag":"invalid-bft-metadata","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"}