{"record":{"id":"65db757b10f5d93b","repo":"hyperledger/fabric","slug":"next-config-attempted-to-change-consensustype-stat","errorCode":null,"errorMessage":"next config attempted to change ConsensusType.State to %s, but capability is disabled","messagePattern":"next config attempted to change ConsensusType\\.State to (.+?), but capability is disabled","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/msgprocessor/maintenancefilter.go","lineNumber":96,"sourceCode":"// transition rules of consensus-type migration using maintenance-mode.\nfunc (mf *MaintenanceFilter) inspect(configEnvelope *cb.ConfigEnvelope, ordererConfig channelconfig.Orderer) error {\n\tif configEnvelope.LastUpdate == nil {\n\t\treturn errors.Errorf(\"updated config does not include a config update\")\n\t}\n\n\tbundle, err := channelconfig.NewBundle(mf.support.ChannelID(), configEnvelope.Config, mf.bccsp)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to parse config\")\n\t}\n\n\tnextOrdererConfig, ok := bundle.OrdererConfig()\n\tif !ok {\n\t\treturn errors.New(\"next config is missing orderer group\")\n\t}\n\n\tif !ordererConfig.Capabilities().ConsensusTypeMigration() {\n\t\tif nextState := nextOrdererConfig.ConsensusState(); nextState != orderer.ConsensusType_STATE_NORMAL {\n\t\t\treturn errors.Errorf(\"next config attempted to change ConsensusType.State to %s, but capability is disabled\", nextState)\n\t\t}\n\t\tif ordererConfig.ConsensusType() != nextOrdererConfig.ConsensusType() {\n\t\t\treturn errors.Errorf(\"next config attempted to change ConsensusType.Type from %s to %s, but capability is disabled\",\n\t\t\t\tordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())\n\t\t}\n\t\treturn nil\n\t}\n\n\t// Entry to- and exit from- maintenance-mode should not be accompanied by any other change.\n\tif ordererConfig.ConsensusState() != nextOrdererConfig.ConsensusState() {\n\t\tif err1Change := mf.ensureConsensusTypeChangeOnly(configEnvelope); err1Change != nil {\n\t\t\treturn err1Change\n\t\t}\n\t\tif ordererConfig.ConsensusType() != nextOrdererConfig.ConsensusType() {\n\t\t\treturn errors.Errorf(\"attempted to change ConsensusType.Type from %s to %s, but ConsensusType.State is changing from %s to %s\",\n\t\t\t\tordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType(), ordererConfig.ConsensusState(), nextOrdererConfig.ConsensusState())\n\t\t}\n\t\tif !bytes.Equal(nextOrdererConfig.ConsensusMetadata(), ordererConfig.ConsensusMetadata()) {","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/msgprocessor/maintenancefilter.go#L78-L114","documentation":"inspect rejects a config update that changes orderer ConsensusType.State while the ConsensusTypeMigration capability is disabled in the channel. State may only leave STATE_NORMAL when migration capability is enabled, so any proposed STATE_MAINTENANCE transition fails with the proposed state name in the message.","triggerScenarios":"Submitting a config update setting orderer group's ConsensusType.State to STATE_MAINTENANCE (or any non-NORMAL value) on a channel whose capabilities do not include ConsensusTypeMigration (pre-V2_0 capability or V3 channel without it).","commonSituations":"Operator begins raft-to-BFT migration without first enabling the migration capability; channel created with older capabilities; capability update not committed on the orderer group.","solutions":["First enable the ConsensusTypeMigration capability (channel + orderer capabilities, e.g. V2_0 or per the migration guide) in a separate config update","Verify with configtxlator that capabilities.ConsensusTypeMigration() is true on the current channel","Retry the maintenance-mode entry after the capability update has been committed"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"oc, _ := support.OrdererConfig()\nif !oc.Capabilities().ConsensusTypeMigration() {\n\treturn errors.New(\"enable ConsensusTypeMigration capability before entering maintenance mode\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Enable V2_0+ capabilities (channel and orderer) as migration step zero","Commit the capability update before any STATE_MAINTENANCE update","Verify capabilities via configtxlator after enabling"],"tags":["ordering","capability","consensus-migration","maintenance-mode"],"backgroundTag":"migration-capability-disabled","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"}